home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / os2 / bind493a.zip / named / ns_resp.c < prev    next >
C/C++ Source or Header  |  1995-12-29  |  67KB  |  2,594 lines

  1. #if !defined(lint) && !defined(SABER)
  2. static char sccsid[] = "@(#)ns_resp.c    4.65 (Berkeley) 3/3/91";
  3. static char rcsid[] = "$Id: ns_resp.c,v 8.18 1995/12/29 21:08:13 vixie Exp $";
  4. #endif /* not lint */
  5.  
  6. /*
  7.  * ++Copyright++ 1986, 1988, 1990
  8.  * -
  9.  * Copyright (c) 1986, 1988, 1990
  10.  *    The Regents of the University of California.  All rights reserved.
  11.  * 
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions and the following disclaimer.
  17.  * 2. Redistributions in binary form must reproduce the above copyright
  18.  *    notice, this list of conditions and the following disclaimer in the
  19.  *    documentation and/or other materials provided with the distribution.
  20.  * 3. All advertising materials mentioning features or use of this software
  21.  *    must display the following acknowledgement:
  22.  *     This product includes software developed by the University of
  23.  *     California, Berkeley and its contributors.
  24.  * 4. Neither the name of the University nor the names of its contributors
  25.  *    may be used to endorse or promote products derived from this software
  26.  *    without specific prior written permission.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38.  * SUCH DAMAGE.
  39.  * -
  40.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  41.  * 
  42.  * Permission to use, copy, modify, and distribute this software for any
  43.  * purpose with or without fee is hereby granted, provided that the above
  44.  * copyright notice and this permission notice appear in all copies, and that
  45.  * the name of Digital Equipment Corporation not be used in advertising or
  46.  * publicity pertaining to distribution of the document or software without
  47.  * specific, written prior permission.
  48.  * 
  49.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  50.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  51.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  52.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  53.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  54.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  55.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  56.  * SOFTWARE.
  57.  * -
  58.  * --Copyright--
  59.  */
  60.  
  61. #include <sys/param.h>
  62. #include <sys/socket.h>
  63. #include <sys/file.h>
  64. #include <netinet/in.h>
  65. #include <arpa/nameser.h>
  66. #include <arpa/inet.h>
  67. #include <syslog.h>
  68. #include <errno.h>
  69. #include <stdio.h>
  70. #include <resolv.h>
  71.  
  72. #include "named.h"
  73.  
  74. static void        check_root __P((void)),
  75.             check_ns __P((void));
  76.  
  77. static u_int8_t        norootlogged[MAXCLASS];    /* XXX- should be a bitmap */
  78.  
  79. static const char    skipnameFailedAnswer[] = "skipname failed in answer",
  80.             skipnameFailedAuth[] =    "skipname failed in authority",
  81.             skipnameFailedQuery[] =    "skipname failed in query",
  82.             outofDataQuery[] =    "ran out of data in query",
  83.             outofDataAnswer[] =    "ran out of data in answer",
  84.             notSingleQuery[] =    "not exactly one query",
  85.             expandFailedQuery[] =    "dn_expand failed in query",
  86.             expandFailedAnswer[] =    "dn_expand failed in answer",
  87.             expandFailedAuth[] =    "dn_expand failed in authority",
  88.             outofDataAuth[] =    "ran out of data in authority",
  89.             dlenOverrunAnswer[] =    "dlen overrun in answer",
  90.             dlenOverrunAuth[] =    "dlen overrun in authority",
  91.             dlenUnderrunAnswer[] =    "dlen underrun in answer",
  92.             outofDataFinal[] =    "out of data in final pass",
  93.             outofDataAFinal[] =    "out of data after final pass",
  94.             editFailed[] =        "edit of response failed";
  95.  
  96. static char *
  97. learntFrom(qp, server)
  98.     struct qinfo *qp;
  99.     struct sockaddr_in *server;
  100. {
  101.     static char *buf = NULL;
  102.     char *a, *ns, *na;
  103.     struct databuf *db;
  104.     char nsbuf[20];
  105.     char abuf[20];
  106.     int i;
  107.     
  108.     if (buf) {
  109.         free(buf);
  110.         buf = NULL;
  111.     }
  112.  
  113.     a = ns = na = "<Not Available>";
  114.  
  115.     for (i = 0; i < (int)qp->q_naddr; i++) {
  116.         if (qp->q_addr[i].ns_addr.sin_addr.s_addr ==
  117.             server->sin_addr.s_addr) {
  118.             db = qp->q_addr[i].ns;
  119.             if (db) {
  120. #ifdef STATS
  121.                 if (db->d_ns) {
  122.                     strcpy(nsbuf,
  123.                            inet_ntoa(db->d_ns->addr));
  124.                     ns = nsbuf;
  125.                 } else {
  126.                     ns = zones[db->d_zone].z_origin;
  127.                 }
  128. #endif
  129.  
  130. #ifdef NCACHE
  131.                 if (!db->d_rcode)
  132. #endif
  133.                     na = (char*)qp->q_addr[i].ns->d_data;
  134.             }
  135.  
  136. #ifdef STATS
  137.             db = qp->q_addr[i].nsdata;
  138.             if (db) {
  139.                 if (db->d_ns) {
  140.                     strcpy(abuf,
  141.                            inet_ntoa(db->d_ns->addr));
  142.                     a = abuf;
  143.                 } else {
  144.                     a = zones[db->d_zone].z_origin;
  145.                 }
  146.             }
  147. #endif
  148.             break;
  149.         }
  150.     }
  151.  
  152.     if ((a == ns) && (ns == na))    /* all "UNKNOWN" */
  153.         return ("");
  154.     
  155. #ifdef STATS
  156. # define LEARNTFROM " '%s': learnt (A=%s,NS=%s)"
  157. #else
  158. # define LEARNTFROM " '%s'"
  159. #endif
  160.     buf = malloc(strlen(a = (*a ? a : "\".\"")) +
  161.              strlen(ns = (*ns ? ns : "\".\"")) +
  162.              strlen(na = (*na ? na : "\".\"")) +
  163.              sizeof(LEARNTFROM));
  164.     if (!buf)
  165.         return ("");
  166.     sprintf(buf, LEARNTFROM, na, a, ns);
  167.     return (buf);
  168. }
  169.  
  170. void
  171. ns_resp(msg, msglen)
  172.     u_char *msg;
  173.     int msglen;
  174. {
  175.     register struct qinfo *qp;
  176.     register HEADER *hp;
  177.     register struct qserv *qs;
  178.     register struct databuf *ns, *ns2;
  179.     register u_char *cp;
  180.     u_char *eom = msg + msglen;
  181.     register u_char *tempcp;
  182. #ifdef VALIDATE
  183.     struct sockaddr_in *server = &from_addr;
  184.     struct { char *name; int type, class; u_int cred; } defer_rm[99];
  185.     int defer_rm_count;
  186. #endif
  187.     struct sockaddr_in *nsa;
  188.     struct databuf *nsp[NSMAX];
  189.     int i, c, n, qdcount, ancount, aucount, nscount, arcount;
  190.     int qtype, qclass, dbflags;
  191.     int restart;    /* flag for processing cname response */
  192.     int validanswer;
  193.     int cname;
  194.     int count, founddata, foundname;
  195.     int buflen;
  196.     int newmsglen;
  197.     char name[MAXDNAME], qname[MAXDNAME];
  198.     char *dname;
  199.     const char *fname;
  200.     const char *formerrmsg = "brain damage";
  201.     u_char newmsg[PACKETSZ];
  202.     u_char **dpp, *tp;
  203.     time_t rtrip;
  204.     struct hashbuf *htp;
  205.     struct namebuf *np;
  206.     struct netinfo *lp;
  207.     struct fwdinfo *fwd;
  208.  
  209.     nameserIncr(from_addr.sin_addr, nssRcvdR);
  210. #ifdef  DATUMREFCNT
  211.     nsp[0] = NULL;
  212. #endif
  213.     hp = (HEADER *) msg;
  214.     if ((qp = qfindid(hp->id)) == NULL ) {
  215.         dprintf(1, (ddt, "DUP? dropped (id %d)\n", ntohs(hp->id)));
  216.         nameserIncr(from_addr.sin_addr, nssRcvdDupR);
  217.         return;
  218.     }
  219.  
  220.     dprintf(2, (ddt, "Response (%s %s %s) nsid=%d id=%d\n",
  221.             (qp->q_flags & Q_SYSTEM) ?"SYSTEM" :"USER",
  222.             (qp->q_flags & Q_PRIMING) ?"PRIMING" :"NORMAL",
  223.             (qp->q_flags & Q_ZSERIAL) ?"ZSERIAL" :"-",
  224.             ntohs(qp->q_nsid), ntohs(qp->q_id)));
  225.  
  226.     /*
  227.      * Here we handle high level formatting problems by parsing the header.
  228.      */
  229.     qdcount = ntohs(hp->qdcount);
  230.     ancount = ntohs(hp->ancount);
  231.     aucount = ntohs(hp->nscount);    /* !!! */
  232.     arcount = ntohs(hp->arcount);
  233.     free_addinfo();        /* sets addcount to zero */
  234.     cp = msg + HFIXEDSZ;
  235.     dpp = dnptrs;
  236.     *dpp++ = msg;
  237.     if ((*cp & INDIR_MASK) == 0)
  238.         *dpp++ = cp;
  239.     *dpp = NULL;
  240.     if (qdcount == 1) {
  241.         n = dn_expand(msg, eom, cp, qname, sizeof(qname));
  242.         if (n <= 0) {
  243.             formerrmsg = expandFailedQuery;
  244.             goto formerr;
  245.         }
  246.         cp += n;
  247.         GETSHORT(qtype, cp);
  248.         GETSHORT(qclass, cp);
  249.         if (cp > eom) {
  250.             formerrmsg = outofDataQuery;
  251.             goto formerr;
  252.         }
  253.         if (qp->q_msg && qp->q_msglen &&
  254.             !res_nameinquery(qname, qtype, qclass,
  255.                      qp->q_msg, qp->q_msg + qp->q_msglen)) {
  256.             char msgbuf[MAXDNAME*2];
  257.  
  258.             sprintf(msgbuf,
  259.                 "query section mismatch (%s %s %s)",
  260.                 qname, p_class(qclass), p_type(qtype));
  261.             formerrmsg = msgbuf;
  262.             goto formerr;
  263.         }
  264.     } else {
  265.         /* Pedantic. */
  266.         qname[0] = '\0';
  267.         qtype = 0;
  268.         qclass = 0;
  269.     }
  270.  
  271.     /* cp now points after the query section. */
  272.  
  273.     /*
  274.      *  Here we handle bad responses from servers.
  275.      *  Several possibilities come to mind:
  276.      *    The server is sick and returns SERVFAIL
  277.      *    The server returns some garbage opcode (it's sick)
  278.      *    The server can't understand our query and return FORMERR
  279.      *  In all these cases, we drop the packet, disable retries on
  280.      *  this server and immediately force a retry.
  281.      */
  282.     if ((hp->rcode != NOERROR && hp->rcode != NXDOMAIN)
  283.         || (hp->opcode != QUERY
  284. #ifdef BIND_NOTIFY
  285.         && hp->opcode != NS_NOTIFY_OP
  286. #endif
  287.         )) {
  288.         dprintf(2, (ddt, "resp: error (ret %d, op %d), dropped\n",
  289.                 hp->rcode, hp->opcode));
  290.         switch (hp->rcode) {
  291.         case SERVFAIL:
  292.             nameserIncr(from_addr.sin_addr, nssRcvdFail);
  293.             break;
  294.         case FORMERR:
  295.             nameserIncr(from_addr.sin_addr, nssRcvdFErr);
  296.             break;
  297.         default:
  298.             nameserIncr(from_addr.sin_addr, nssRcvdErr);
  299.             break;
  300.         }
  301.         /* mark server as bad */
  302.         if (!qp->q_fwd)
  303.             for (i = 0; i < (int)qp->q_naddr; i++)
  304.                 if (qp->q_addr[i].ns_addr.sin_addr.s_addr
  305.                     == from_addr.sin_addr.s_addr)
  306.                     qp->q_addr[i].nretry = MAXRETRY;
  307.         /*
  308.          * XXX:    doesn't handle responses sent from the wrong
  309.          *    interface on a multihomed server.
  310.          */
  311.         if (qp->q_fwd ||
  312.             qp->q_addr[qp->q_curaddr].ns_addr.sin_addr.s_addr
  313.             == from_addr.sin_addr.s_addr)
  314.             retry(qp);
  315.         return;
  316.     }
  317.  
  318.     if (qdcount != 1) {
  319.         /* We don't generate or forward these (yet). */
  320.         formerrmsg = notSingleQuery;
  321.         goto formerr;
  322.     }
  323.  
  324. #ifdef ALLOW_UPDATES
  325.     if ( (hp->rcode == NOERROR) &&
  326.          (hp->opcode == UPDATEA || hp->opcode == UPDATED ||
  327.           hp->opcode == UPDATEDA || hp->opcode == UPDATEM ||
  328.           hp->opcode == UPDATEMA) ) {
  329.         /*
  330.          * Update the secondary's copy, now that the primary
  331.          * successfully completed the update.  Zone doesn't matter
  332.          * for dyn. update -- doupdate calls findzone to find it
  333.          */
  334.         /* XXX - DB_C_AUTH may be wrong */
  335.         (void) doupdate(qp->q_msg, qp->q_msglen, qp->q_msg + HFIXEDSZ,
  336.                 0, (struct databuf *)0, 0, DB_C_AUTH);
  337.         dprintf(3, (ddt, "resp: leaving, UPDATE*\n"));
  338.         /* return code filled in by doupdate */
  339.         goto return_msg;
  340.     }
  341. #endif /* ALLOW_UPDATES */
  342.  
  343.     /*
  344.      * Determine if the response came from a forwarder.  Packets from
  345.      * anyplace not listed as a forwarder or as a server to whom we
  346.      * might have forwarded the query will be dropped.
  347.      */
  348.     for (fwd = fwdtab;  fwd != (struct fwdinfo *)NULL;  fwd = fwd->next) {
  349.         if (fwd->fwdaddr.sin_addr.s_addr ==
  350.             from_addr.sin_addr.s_addr) {
  351.             /* XXX - should put this in STATS somewhere. */
  352.             break;
  353.         }
  354.     }
  355.     /*
  356.      * XXX:    note bad ambiguity here.  if one of our forwarders is also
  357.      *    a delegated server for some domain, then we will not update
  358.      *    the RTT information on any replies we get from those servers.
  359.      *    Workaround: disable recursion on authoritative servers so that
  360.      *    the ambiguity does not arise.
  361.      */
  362.     /*
  363.      * If we weren't using a forwarder, find the qinfo pointer and update
  364.      * the rtt and fact that we have called on this server before.
  365.      */
  366.     if (fwd == (struct fwdinfo *)NULL) {
  367.         struct timeval *stp;
  368.  
  369.         for (n = 0, qs = qp->q_addr; (u_int)n < qp->q_naddr; n++, qs++)
  370.             if (qs->ns_addr.sin_addr.s_addr ==
  371.                 from_addr.sin_addr.s_addr)
  372.                 break;
  373.         if ((u_int)n >= qp->q_naddr) {
  374.             if (!haveComplained((char*)from_addr.sin_addr.s_addr,
  375.                         "unexpected source")) {
  376.                 syslog(LOG_INFO,
  377.                        "Response from unexpected source (%s)",
  378.                        sin_ntoa(&from_addr));
  379.             }
  380.             /* 
  381.              * We don't know who this response came from so it
  382.              * gets dropped on the floor.
  383.              */
  384.             return;
  385.         }
  386.         stp = &qs->stime;
  387.  
  388.         /* Handle response from different (untried) interface */
  389.         if ((qs->ns != NULL) && (stp->tv_sec == 0)) {
  390.             ns = qs->ns;
  391.             while (qs > qp->q_addr
  392.                    && (qs->stime.tv_sec == 0 || qs->ns != ns))
  393.                 qs--;
  394.             *stp = qs->stime;
  395.             /* XXX - sometimes stp still ends up pointing to
  396.              * a zero timeval, in spite of the above attempt.
  397.              * Why?  What should we do about it?
  398.              */
  399.             dprintf(1, (ddt,
  400.                   "Response from unused address %s, assuming %s\n",
  401.                     sin_ntoa(&from_addr),
  402.                     sin_ntoa(&qs->ns_addr)));
  403.             /* XXX - catch aliases here */
  404.         }
  405.  
  406.         /* compute query round trip time */
  407.         /* XXX - avoid integer overflow, which is quite likely if stp
  408.          * points to a zero timeval (see above).
  409.          * rtrip is of type time_t, which we assume is at least
  410.          * as big as an int.
  411.          */
  412.         if ((tt.tv_sec - stp->tv_sec) > (INT_MAX-999)/1000) {
  413.             rtrip = INT_MAX;
  414.         } else {
  415.             rtrip = ((tt.tv_sec - stp->tv_sec) * 1000 +
  416.                  (tt.tv_usec - stp->tv_usec) / 1000);
  417.         }
  418.         
  419.         dprintf(3, (ddt, "stime %lu/%lu  now %lu/%lu rtt %ld\n",
  420.                 (u_long)stp->tv_sec, (u_long)stp->tv_usec,
  421.                 (u_long)tt.tv_sec, (u_long)tt.tv_usec,
  422.                 (long)rtrip));
  423.  
  424.         /* prevent floating point overflow, limit to 1000 sec */
  425.         if (rtrip > 1000000) {
  426.             rtrip = 1000000;
  427.         }
  428.         ns = qs->nsdata;
  429.         /*
  430.          * Don't update nstime if this doesn't look
  431.          * like an address databuf now.            XXX
  432.          */
  433.         if (ns && (ns->d_type==T_A) && (ns->d_class==qs->ns->d_class)){
  434.             if (ns->d_nstime == 0)
  435.                 ns->d_nstime = (u_int32_t)rtrip;
  436.             else
  437.                 ns->d_nstime = (u_int32_t)
  438.                         (ns->d_nstime * ALPHA 
  439.                          +
  440.                          (1-ALPHA) * (u_int32_t)rtrip);
  441.             /* prevent floating point overflow,
  442.              * limit to 1000 sec
  443.              */
  444.             if (ns->d_nstime > 1000000)
  445.                 ns->d_nstime = 1000000;
  446.         }
  447.  
  448.         /*
  449.          * Record the source so that we do not use this NS again.
  450.          */
  451.         if (ns && qs->ns && (qp->q_nusedns < NSMAX)) {
  452.             qp->q_usedns[qp->q_nusedns++] = qs->ns;
  453.             dprintf(2, (ddt, "NS #%d addr %s used, rtt %d\n",
  454.                     n, sin_ntoa(&qs->ns_addr),
  455.                     ns->d_nstime));
  456.         }
  457.  
  458.         /*
  459.          * Penalize those who had earlier chances but failed
  460.          * by multiplying round-trip times by BETA (>1).
  461.          * Improve nstime for unused addresses by applying GAMMA.
  462.          * The GAMMA factor makes unused entries slowly
  463.          * improve, so they eventually get tried again.
  464.          * GAMMA should be slightly less than 1.
  465.          * Watch out for records that may have timed out
  466.          * and are no longer the correct type.            XXX
  467.          */
  468.         
  469.         for (n = 0, qs = qp->q_addr;
  470.              (u_int)n < qp->q_naddr;
  471.              n++, qs++) {
  472.             ns2 = qs->nsdata;
  473.             if ((!ns2) || (ns2 == ns))
  474.                 continue;
  475.             if (ns2->d_type != T_A ||
  476.                 ns2->d_class != qs->ns->d_class)    /* XXX */
  477.                 continue;
  478.             if (qs->stime.tv_sec) {
  479.                 if (ns2->d_nstime == 0)
  480.                 ns2->d_nstime = (u_int32_t)(rtrip * BETA);
  481.                 else
  482.                 ns2->d_nstime = (u_int32_t)(
  483.                     ns2->d_nstime * BETA + (1-ALPHA) * rtrip
  484.                 );
  485.                 if (ns2->d_nstime > 1000000)
  486.                 ns2->d_nstime = 1000000;
  487.             } else
  488.                 ns2->d_nstime = (u_int32_t)(ns2->d_nstime * GAMMA);
  489.             dprintf(2, (ddt, "NS #%d %s rtt now %d\n", n,
  490.                     sin_ntoa(&qs->ns_addr),
  491.                     ns2->d_nstime));
  492.         }
  493.     }
  494.  
  495. #ifdef BIND_NOTIFY
  496.     /* for now, NOTIFY isn't defined for ANCOUNT!=0, AUCOUNT!=0,
  497.      * or ADCOUNT!=0.  therefore the only real work to be done for
  498.      * a NOTIFY-QR is to remove it from the query queue.
  499.      */
  500.     if (hp->opcode == NS_NOTIFY_OP) {
  501.         qremove(qp);
  502.         return;
  503.     }
  504. #endif
  505.  
  506. #ifdef LAME_DELEGATION
  507.     /*
  508.      *  Non-authoritative, no answer, no error
  509.      */
  510.     if (qdcount == 1 && hp->rcode == NOERROR && !hp->aa && ancount == 0
  511.         && aucount > 0
  512. #ifdef BIND_NOTIFY
  513.         && hp->opcode != NS_NOTIFY_OP
  514. #endif
  515.         ) {
  516.         u_char *tp;
  517.         int type, class;
  518. #ifdef DEBUG
  519.         if (debug > 0)
  520.             fp_nquery(msg, msglen, ddt);
  521. #endif
  522.         /*
  523.          * Since there is no answer section (ancount == 0),
  524.          * we must be pointing at the authority section (aucount > 0).
  525.          */
  526.         tp = cp;
  527.         n = dn_expand(msg, eom, tp, name, sizeof name);
  528.         if (n < 0) {
  529.             formerrmsg = expandFailedAuth;
  530.             goto formerr;
  531.         }
  532.         tp += n;
  533.         GETSHORT(type, tp);
  534.         if (tp >= eom) {
  535.             formerrmsg = outofDataAuth;
  536.             goto formerr;
  537.         }
  538.         GETSHORT(class, tp);
  539.         if (tp >= eom) {
  540.             formerrmsg = outofDataAuth;
  541.             goto formerr;
  542.         }
  543.  
  544.         /*
  545.          * If the answer delegates us either to the same level in
  546.          * the hierarchy or closer to the root, we consider this
  547.          * server lame.  Note that for now we only log the message
  548.          * if the T_NS was C_IN, which is technically wrong (NS is
  549.          * visible in all classes) but necessary anyway (non-IN
  550.          * classes tend to not have good strong delegation graphs).
  551.          */
  552.  
  553.         if (type == T_NS && samedomain(qp->q_domain, name)) {
  554.             nameserIncr(from_addr.sin_addr, nssRcvdLDel);
  555.             /* mark server as bad */
  556.             if (!qp->q_fwd)
  557.                 for (i = 0; i < (int)qp->q_naddr; i++)
  558.                 if (qp->q_addr[i].ns_addr.sin_addr.s_addr
  559.                     == from_addr.sin_addr.s_addr)
  560.                     qp->q_addr[i].nretry = MAXRETRY;
  561. #ifdef LAME_LOGGING
  562.             if (class == C_IN &&
  563.                 !haveComplained((char*)nhash(sin_ntoa(&from_addr)),
  564.                         (char*)nhash(qp->q_domain)))
  565.                 syslog(LAME_LOGGING,
  566.                       "Lame server on '%s' (in '%s'?): %s%s\n",
  567.                        qname, qp->q_domain, 
  568.                        sin_ntoa(&from_addr),
  569.                        learntFrom(qp, &from_addr));
  570.  
  571. #endif /* LAME_LOGGING */
  572.             /* XXX - doesn't handle responses sent from the wrong
  573.              * interface on a multihomed server
  574.              */
  575.             if (qp->q_fwd ||
  576.                 qp->q_addr[qp->q_curaddr].ns_addr.sin_addr.s_addr
  577.                 == from_addr.sin_addr.s_addr)
  578.                 retry(qp);
  579.             return;
  580.         }
  581.     }
  582. #endif /* LAME_DELEGATION */
  583.  
  584.     if (qp->q_flags & Q_ZSERIAL) {
  585.         if (hp->aa && ancount > 0 && hp->rcode == NOERROR &&
  586.             qtype == T_SOA && ((qclass == C_IN) || (qclass == C_HS))) {
  587.             int n;
  588.             u_int16_t type, class, dlen;
  589.             u_int32_t serial;
  590.             u_char *tp = cp;
  591.  
  592.             n = dn_expand(msg, eom, tp, name, sizeof name);
  593.             if (n < 0) {
  594.                 formerrmsg = expandFailedAnswer;
  595.                 goto formerr;
  596.             }
  597.             tp += n;          /* name */
  598.             GETSHORT(type, tp);    /* type */
  599.             GETSHORT(class, tp);    /* class */
  600.             tp += INT32SZ;        /* ttl */
  601.             GETSHORT(dlen, tp);     /* dlen */
  602.             if (tp >= eom) {
  603.                 formerrmsg = outofDataAnswer;
  604.                 goto formerr;
  605.             }
  606.             if (strcasecmp(qname, name) ||
  607.                 qtype != type ||
  608.                 qclass != class) {
  609.                 char msgbuf[MAXDNAME*2];
  610.  
  611.                 sprintf(msgbuf,
  612.                     "qserial answer mismatch (%s %s %s)",
  613.                     name, p_class(class), p_type(type));
  614.                 formerrmsg = msgbuf;
  615.                 goto formerr;
  616.             }
  617.             if ((u_int)dlen < (5 * INT32SZ)) {
  618.                 formerrmsg = dlenUnderrunAnswer;
  619.                 goto formerr;
  620.             }
  621.  
  622.             if (0 >= (n = dn_skipname(tp, eom))) {
  623.                 formerrmsg = skipnameFailedAnswer;
  624.                 goto formerr;
  625.             }
  626.             tp += n;          /* mname */
  627.             if (0 >= (n = dn_skipname(tp, eom))) {
  628.                 formerrmsg = skipnameFailedAnswer;
  629.                 goto formerr;
  630.             }
  631.             tp += n;          /* rname */
  632.             GETLONG(serial, tp);
  633.  
  634.             qserial_answer(qp, serial);
  635.         }
  636.         qremove(qp);
  637.         return;
  638.     }
  639.  
  640.     /*
  641.      * Add the info received in the response to the data base.
  642.      */
  643.     c = ancount + aucount + arcount;
  644.  
  645.     /* -ve $ing non-existence of record, must handle non-authoritative
  646.      * NOERRORs with c == 0.
  647.      */
  648.     if (!hp->aa && hp->rcode == NOERROR && c == 0)
  649.         goto return_msg;
  650.  
  651. #ifdef notdef
  652.     /*
  653.      * If the request was for a CNAME that doesn't exist,
  654.      * but the name is valid, fetch any other data for the name.
  655.      * DON'T do this now, as it will requery if data are already
  656.      * in the cache (maybe later with negative caching).
  657.      */
  658.     if (type == T_CNAME && c == 0 && hp->rcode == NOERROR
  659.         && !(qp->q_flags & Q_SYSTEM)) {
  660.         dprintf(4, (ddt, "resp: leaving, no CNAME\n"));
  661.  
  662.         /* Cause us to put it in the cache later */
  663.         prime(class, T_ANY, qp);
  664.  
  665.         /* Nothing to store, just give user the answer */
  666.         goto return_msg;
  667.     }
  668. #endif /* notdef */
  669.  
  670.     if (qp->q_flags & Q_SYSTEM)
  671.         dbflags = DB_NOTAUTH | DB_NODATA;
  672.     else
  673.         dbflags = DB_NOTAUTH | DB_NODATA | DB_NOHINTS;
  674.     count = c;
  675.     if (qp->q_flags & Q_PRIMING)
  676.         dbflags |= DB_PRIMING;
  677.     if (hp->tc) {
  678.         count -= arcount;    /* truncation had to affect this */
  679.         if (!arcount) {
  680.             count -= aucount;    /* guess it got this too */
  681.         }
  682.         if (!(arcount || aucount)) {
  683.             count -= ancount;    /* things are pretty grim */
  684.         }
  685.         /* XXX - should retry this query with TCP */
  686.     }
  687.  
  688.     tp = cp;
  689.  
  690.     restart = 0;
  691.     validanswer = 0;
  692.     nscount = 0;
  693.     cname = 0;
  694. #ifdef VALIDATE
  695.     defer_rm_count = 0;
  696. #endif
  697.  
  698.     for (i = 0; i < count; i++) {
  699.         struct databuf *ns3 = NULL;
  700.         u_char cred;
  701.         int VCode;
  702.         u_int16_t type, class;
  703.  
  704.         if (cp >= eom) {
  705.             formerrmsg = outofDataFinal;
  706.             goto formerr;
  707.         }
  708.  
  709.         /* Get the DNAME. */
  710.         tempcp = cp;
  711.         n = dn_expand(msg, eom, tempcp, name, sizeof name);
  712.         if (n <= 0) {
  713.             formerrmsg = outofDataFinal;
  714.             goto formerr;
  715.         }
  716.         tempcp += n;
  717.         GETSHORT(type, tempcp);
  718.         GETSHORT(class, tempcp);
  719.  
  720.         /*
  721.          * See if there are any NS RRs in the authority section
  722.          * for the negative caching logic below.  We'll count
  723.          * these before validation.
  724.          */
  725.         if (type == T_NS && i >= ancount && i < ancount + aucount)
  726.             nscount++;
  727.  
  728.         /* Decide what credibility this ought to have in the cache. */
  729.         if (i < ancount)
  730.             cred = (hp->aa && !strcasecmp(name, qname))
  731.                 ? DB_C_AUTH
  732.                 : DB_C_ANSWER;
  733.         else
  734.             cred = (qp->q_flags & Q_PRIMING)
  735.                 ? DB_C_ANSWER
  736.                 : DB_C_ADDITIONAL;
  737. #ifdef VALIDATE
  738.         if ((n = dovalidate(msg, msglen, cp, 0,
  739.                     dbflags, qp->q_domain, server,
  740.                     &VCode)) < 0) {
  741.             formerrmsg = outofDataFinal;
  742.             goto formerr;
  743.         }
  744.         if (VCode == INVALID && !(qp->q_flags & Q_SYSTEM)) {
  745.             /*
  746.              * If anything in the answer section fails
  747.              * validation this means that it definitely did
  748.              * not reside below the domain owning the NS RRs
  749.              * that we sent the query to.  This means either
  750.              * that it was the target of a CNAME early in the
  751.              * response, in which case we will treat this the
  752.              * same as if the answer was incomplete and restart
  753.              * the query on the CNAME target, or that someone
  754.              * was trying to spoof us.
  755.              */
  756.             if (i < ancount)
  757.                 restart = 1;
  758.             /*
  759.              * Restart or no, if we're here it means we are not
  760.              * going to cache this RR.  That being the case, we
  761.              * must burn down whatever partial RRset we've got
  762.              * in the cache now, lest we inadvertently answer
  763.              * with a truncated RRset in some future section.
  764.              */
  765.             for (c = 0; c < defer_rm_count; c++)
  766.                 if (!strcasecmp(defer_rm[c].name, name) &&
  767.                     defer_rm[c].class == class &&
  768.                     defer_rm[c].type == type)
  769.                     break;
  770.             if (c < defer_rm_count) {
  771.                 if (defer_rm[c].cred < cred)
  772.                     defer_rm[c].cred = cred;
  773.             } else {
  774.                 if (defer_rm_count+1 >=
  775.                     (sizeof defer_rm / sizeof defer_rm[0])) {
  776.                     formerrmsg = "too many RRs in ns_resp";
  777.                     goto formerr;
  778.                 }
  779.                 defer_rm[defer_rm_count].name = savestr(name);
  780.                 defer_rm[defer_rm_count].type = type;
  781.                 defer_rm[defer_rm_count].class = class;
  782.                 defer_rm[defer_rm_count].cred = cred;
  783.                 defer_rm_count++;
  784.             }
  785.         } else {
  786. #endif
  787.         if (i < ancount) {
  788.             /*
  789.              * If there are any non-CNAME RRs (or
  790.              * CNAME RRs if they are an acceptable)
  791.              * then the query is complete unless an
  792.              * intermediate CNAME didn't pass validation,
  793.              * but that's OK.
  794.              */
  795.             if (type != T_CNAME || qtype == T_CNAME ||
  796.                 qtype == T_ANY)
  797.                 validanswer = 1;
  798.             else
  799.                 cname = 1;
  800.         }
  801.         n = doupdate(msg, msglen, cp, 0, &ns3, dbflags, cred);
  802. #ifdef VALIDATE
  803.         }
  804. #endif
  805.         if (n < 0) {
  806.             dprintf(1, (ddt, "resp: leaving, doupdate failed\n"));
  807.             formerrmsg = outofDataFinal;
  808.             goto formerr;
  809.         }
  810.         cp += n;
  811.     }
  812. #ifdef VALIDATE
  813.     if (defer_rm_count > 0) {
  814.         for (i = 0; i < defer_rm_count; i++) {
  815.             register struct databuf *db = NULL;
  816.  
  817.             fname = "";
  818.             htp = hashtab;        /* lookup relative to root */
  819.             np = nlookup(defer_rm[i].name, &htp, &fname, 0);
  820.             if (np && fname == defer_rm[i].name &&
  821.                 defer_rm[i].class != C_ANY &&
  822.                 defer_rm[i].type != T_ANY) {
  823.                 /*
  824.                  * If doupdate() wouldn't have cached this
  825.                  * RR anyway, there's no need to delete it.
  826.                  */
  827.                 for (db = np->n_data;
  828.                      db != NULL;
  829.                      db = db->d_next) {
  830.                     if (!db->d_zone &&
  831.                         match(db, defer_rm[i].class,
  832.                           defer_rm[i].type) &&
  833.                         db->d_cred >= defer_rm[i].cred) {
  834.                         break;
  835.                     }
  836.                 }
  837.                 if (db == NULL)
  838.                     delete_all(np, defer_rm[i].class,
  839.                            defer_rm[i].type);
  840.                 /* XXX: should delete name node if empty? */
  841.             }
  842.             syslog(LOG_DEBUG, "defer_rm [%s %s %s] (np%#x, db%#x)",
  843.                    defer_rm[i].name,
  844.                    p_class(defer_rm[i].class),
  845.                    p_type(defer_rm[i].type),
  846.                    np, db);
  847.             free(defer_rm[i].name);
  848.         }
  849.     }
  850. #endif
  851.  
  852.     if (cp > eom) {
  853.         formerrmsg = outofDataAFinal;
  854.         goto formerr;
  855.     }
  856.  
  857.     if ((qp->q_flags & Q_SYSTEM) && ancount) {
  858.         if (qp->q_flags & Q_PRIMING)
  859.             check_root();
  860.         dprintf(3, (ddt, "resp: leaving, SYSQUERY ancount %d\n",
  861.                 ancount));
  862. #ifdef BIND_NOTIFY
  863.         if (qp->q_notifyzone != DB_Z_CACHE) {
  864.             struct zoneinfo *zp = &zones[qp->q_notifyzone];
  865.  
  866.             /*
  867.              * Clear this first since sysnotify() might set it.
  868.              */
  869.             qp->q_notifyzone = DB_Z_CACHE;
  870.             sysnotify(zp->z_origin, zp->z_class, T_SOA);
  871.         }
  872. #endif
  873.         qremove(qp);
  874.         return;
  875.     }
  876.  
  877.     if (ancount && !validanswer)
  878.         /*
  879.          * Everything passed validation but we didn't get the
  880.          * final answer.  The response must have contained
  881.          * a dangling CNAME.  Force a restart of the query.
  882.          */
  883.         restart = 1;
  884.  
  885.     /*
  886.      *  If there are addresses and this is a local query,
  887.      *  sort them appropriately for the local context.
  888.      */
  889. #ifdef SORT_RESPONSE
  890.     if (!restart && ancount > 1 && (lp = local(&qp->q_from)) != NULL) 
  891.         sort_response(tp, ancount, lp, eom);
  892. #endif
  893.  
  894.     /*
  895.      * An answer to a T_ANY query or a successful answer to a
  896.      * regular query with no indirection, then just return answer.
  897.      */
  898.     if (!restart && ancount && (qtype == T_ANY || !qp->q_cmsglen)) {
  899.         dprintf(3, (ddt, "resp: got as much answer as there is\n"));
  900.         goto return_msg;
  901.     }
  902.  
  903.     /*
  904.      * We might want to cache this negative answer.
  905.      */
  906.     if (!ancount &&
  907.         (!nscount || hp->rcode == NXDOMAIN) &&
  908.         (hp->aa || fwd || qclass == C_ANY)) {
  909.         /* we have an authoritative NO */
  910.         dprintf(3, (ddt, "resp: leaving auth NO\n"));
  911.         if (qp->q_cmsglen) {
  912.             /* XXX - what about additional CNAMEs in the chain? */
  913.             msg = qp->q_cmsg;
  914.             msglen = qp->q_cmsglen;
  915.             hp = (HEADER *)msg;
  916.         }
  917. #ifdef NCACHE
  918.         /* answer was NO */
  919.         if (hp->aa &&
  920.             ((hp->rcode == NXDOMAIN) || (hp->rcode == NOERROR))) {
  921.             cache_n_resp(msg, msglen);
  922.         }
  923. #endif /*NCACHE*/
  924.         goto return_msg;
  925.     }
  926.  
  927.     /*
  928.      * All messages in here need further processing.  i.e. they
  929.      * are either CNAMEs or we got referred again.
  930.      */
  931.     count = 0;
  932.     founddata = 0;
  933.     foundname = 0;
  934.     dname = name;
  935.     /*
  936.      * Even with VALIDATE, if restart==0 and ancount > 0, we should
  937.      * have some valid data because because the data in the answer
  938.      * section is owned by the query name and that passes the
  939.      * validation test by definition
  940.      *
  941.      * XXX - the restart stuff doesn't work if any of the answer RRs
  942.      * is not cacheable (TTL==0 or unknown RR type), since all of the
  943.      * answer must pass through the cache and be re-assembled.
  944.      */
  945.     if ((!restart || !cname) && qp->q_cmsglen && ancount) {
  946.         dprintf(1, (ddt, "Cname second pass\n"));
  947.         newmsglen = qp->q_cmsglen;
  948.         bcopy(qp->q_cmsg, newmsg, newmsglen);
  949.     } else {
  950.         newmsglen = msglen;
  951.         bcopy(msg, newmsg, newmsglen);
  952.     }
  953.     hp = (HEADER *) newmsg;
  954.     hp->ancount = htons(0);
  955.     hp->nscount = htons(0);
  956.     hp->arcount = htons(0);
  957.     dnptrs[0] = newmsg;
  958.     dnptrs[1] = NULL;
  959.     cp = newmsg + HFIXEDSZ;
  960.     /*
  961.      * Keep in mind that none of this code works when QDCOUNT>1.
  962.      * cp ends up pointed just past the query section in both cases.
  963.      */
  964.     /*
  965.      * Arrange for dname to contain the query name. The query
  966.      * name can be either the original query name if restart==0
  967.      * or the target of the last CNAME if we are following a
  968.      * CNAME chain and were referred.
  969.      */
  970.     n = dn_expand(newmsg, newmsg + newmsglen, cp, dname,
  971.               sizeof name);
  972.     if (n < 0) {
  973.         dprintf(1, (ddt, "dn_expand failed\n"));
  974.         goto servfail;
  975.     }
  976.     cp += n + QFIXEDSZ;
  977.     buflen = sizeof(newmsg) - (cp - newmsg);
  978.  
  979.     cname = 0;
  980.  try_again:
  981.     dprintf(1, (ddt, "resp: nlookup(%s) qtype=%d\n", dname, qtype));
  982.     fname = "";
  983.     htp = hashtab;        /* lookup relative to root */
  984.     np = nlookup(dname, &htp, &fname, 0);
  985.     dprintf(1, (ddt, "resp: %s '%s' as '%s' (cname=%d)\n",
  986.             np == NULL ? "missed" : "found", dname, fname, cname));
  987.     if (np == NULL || fname != dname)
  988.         goto fetch_ns;
  989.  
  990.     foundname++;
  991.     count = cp - newmsg;
  992.     n = finddata(np, qclass, qtype, hp, &dname, &buflen, &count);
  993.     if (n == 0)
  994.         goto fetch_ns;        /* NO data available */
  995.     cp += n;
  996.     buflen -= n;
  997.     hp->ancount = htons(ntohs(hp->ancount) + (u_int16_t)count);
  998.     if (fname != dname && qtype != T_CNAME && qtype != T_ANY) {
  999.         cname++;
  1000.         goto try_again;
  1001.     }
  1002.     founddata = 1;
  1003.  
  1004.     dprintf(3, (ddt,
  1005.             "resp: foundname=%d, count=%d, founddata=%d, cname=%d\n",
  1006.             foundname, count, founddata, cname));
  1007.  
  1008.  fetch_ns:
  1009.  
  1010.     if (hp->tc)
  1011.         goto return_newmsg;
  1012.  
  1013.     /*
  1014.       * Look for name servers to refer to and fill in the authority
  1015.       * section or record the address for forwarding the query
  1016.       * (recursion desired).
  1017.       */
  1018. #ifdef    DATUMREFCNT
  1019.     free_nsp(nsp);
  1020. #endif
  1021.     switch (findns(&np, qclass, nsp, &count, 0)) {
  1022.     case NXDOMAIN:        /* shouldn't happen */
  1023.         dprintf(3, (ddt, "req: leaving (%s, rcode %d)\n",
  1024.                 dname, hp->rcode));
  1025.         if (!foundname)
  1026.             hp->rcode = NXDOMAIN;
  1027.         if (qclass != C_ANY) {
  1028.             hp->aa = 1;
  1029.             /* XXX:    should return SOA if founddata == 0,
  1030.              *    but old named's are confused by an SOA
  1031.              *    in the auth. section if there's no error.
  1032.              */
  1033.             if (foundname == 0 && np) {
  1034.                 n = doaddauth(hp, cp, buflen, np, nsp[0]);
  1035.                 cp += n;
  1036.                 buflen -= n;
  1037.             }
  1038.         }
  1039.         goto return_newmsg;
  1040.  
  1041.     case SERVFAIL:
  1042.         goto servfail;
  1043.     }
  1044.  
  1045.     if (founddata) {
  1046.         hp = (HEADER *)newmsg;
  1047.         n = add_data(np, nsp, cp, buflen, &count);
  1048.         if (n < 0) {
  1049.             hp->tc = 1;
  1050.             n = (-n);
  1051.         }
  1052.         cp += n;
  1053.         buflen -= n;
  1054.         hp->nscount = htons((u_int16_t)count);
  1055.         goto return_newmsg;
  1056.     }
  1057.  
  1058.     /*
  1059.      *  If we get here, we don't have the answer yet and are about
  1060.      *  to iterate to try and get it.  First, infinite loop avoidance.
  1061.      */
  1062.     if (qp->q_nqueries++ > MAXQUERIES) {
  1063.         dprintf(1, (ddt, "resp: MAXQUERIES exceeded (%s %s %s)\n",
  1064.                 dname, p_class(qclass), p_type(qtype)));
  1065.         syslog(LOG_INFO,
  1066.                "MAXQUERIES exceeded, possible data loop in resolving (%s)",
  1067.                dname);
  1068.         goto servfail;
  1069.     }
  1070.  
  1071.     /* Reset the query control structure */
  1072. #ifdef    DATUMREFCNT
  1073.     /* XXX - this code should be shared with qfree()'s similar logic. */
  1074.     for (i = 0; (u_int)i < qp->q_naddr; i++) {
  1075.         static const char freed[] = "freed", busy[] = "busy";
  1076.         const char *result;
  1077.  
  1078.         if (qp->q_addr[i].ns != NULL) {
  1079.             if ((--(qp->q_addr[i].ns->d_rcnt)))
  1080.                 result = busy;
  1081.             else
  1082.                 result = freed;
  1083.             dprintf(1, (ddt, "ns_resp: ns %s rcnt %d (%s)\n",
  1084.                     qp->q_addr[i].ns->d_data,
  1085.                     qp->q_addr[i].ns->d_rcnt,
  1086.                     result));
  1087.             if (result == freed)
  1088.                 free((char*)qp->q_addr[i].ns);
  1089.         }
  1090.         if (qp->q_addr[i].nsdata != NULL) {
  1091.             if ((--(qp->q_addr[i].nsdata->d_rcnt)))
  1092.                 result = busy;
  1093.             else
  1094.                 result = freed;
  1095.             dprintf(1, (ddt,
  1096.                     "ns_resp: nsdata %08.8X rcnt %d (%s)\n",
  1097.                     *(int32_t *)(qp->q_addr[i].nsdata->d_data),
  1098.                     qp->q_addr[i].nsdata->d_rcnt,
  1099.                     result));
  1100.             if (result == freed)
  1101.                 free((char*)qp->q_addr[i].nsdata);
  1102.         }
  1103.     }
  1104. #endif
  1105.     qp->q_naddr = 0;
  1106.     qp->q_curaddr = 0;
  1107.     qp->q_fwd = fwdtab;
  1108. #if defined(LAME_DELEGATION) || defined(VALIDATE)
  1109.     getname(np, qp->q_domain, sizeof(qp->q_domain));
  1110. #endif /* LAME_DELEGATION */
  1111.     if ((n = nslookup(nsp, qp, dname, "ns_resp")) <= 0) {
  1112.         if (n < 0) {
  1113.             dprintf(3, (ddt, "resp: nslookup reports danger\n"));
  1114.         } else {
  1115.             dprintf(3, (ddt, "resp: no addrs found for NS's\n"));
  1116.         }
  1117.         if (cname)    /* a remote CNAME that does not have data */
  1118.             goto return_newmsg;
  1119.         goto servfail;
  1120.     }
  1121.     for (n = 0; (u_int)n < qp->q_naddr; n++)
  1122.         qp->q_addr[n].stime.tv_sec = 0;
  1123.     if (!qp->q_fwd)
  1124.         qp->q_addr[0].stime = tt;
  1125.     if (cname) {
  1126.          if (qp->q_cname++ == MAXCNAMES) {
  1127.             dprintf(3, (ddt,
  1128.                     "resp: leaving, MAXCNAMES exceeded\n"));
  1129.             goto servfail;
  1130.          }
  1131.         dprintf(1, (ddt, "q_cname = %d\n", qp->q_cname));
  1132.         dprintf(3, (ddt,
  1133.                 "resp: building recursive query; nslookup\n"));
  1134.         if (!qp->q_cmsg) {
  1135.             qp->q_cmsg = qp->q_msg;
  1136.             qp->q_cmsglen = qp->q_msglen;
  1137.         } else if (qp->q_msg)
  1138.             (void) free(qp->q_msg);
  1139.         if ((qp->q_msg = (u_char *)malloc(BUFSIZ)) == NULL) {
  1140.             syslog(LOG_NOTICE, "resp: malloc error\n");
  1141.             goto servfail;
  1142.         }
  1143.         n = res_mkquery(QUERY, dname, qclass, qtype,
  1144.                 NULL, 0, NULL, qp->q_msg, BUFSIZ);
  1145.         if (n < 0) {
  1146.             syslog(LOG_INFO, "resp: res_mkquery(%s) failed",
  1147.                    dname);
  1148.             goto servfail;
  1149.         }
  1150.         qp->q_msglen = n;
  1151.         hp = (HEADER *) qp->q_msg;
  1152.         hp->rd = 0;
  1153.     } else
  1154.         hp = (HEADER *) qp->q_msg;
  1155.     hp->id = qp->q_nsid = htons(nsid_next());
  1156.     if (qp->q_fwd)
  1157.         hp->rd = 1;
  1158.     unsched(qp);
  1159.     schedretry(qp, retrytime(qp));
  1160.     nsa = Q_NEXTADDR(qp, 0);
  1161.     dprintf(1, (ddt, "resp: forw -> %s ds=%d nsid=%d id=%d %dms\n",
  1162.             sin_ntoa(nsa), ds,
  1163.             ntohs(qp->q_nsid), ntohs(qp->q_id),
  1164.             (qp->q_addr[0].nsdata != NULL)
  1165.             ? qp->q_addr[0].nsdata->d_nstime
  1166.             : (-1)));
  1167. #ifdef DEBUG
  1168.     if (debug >= 10)
  1169.         fp_nquery(qp->q_msg, qp->q_msglen, ddt);
  1170. #endif
  1171.     if (sendto(ds, (char*)qp->q_msg, qp->q_msglen, 0,
  1172.            (struct sockaddr *)nsa,
  1173.            sizeof(struct sockaddr_in)) < 0) {
  1174.         if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
  1175.             syslog(LOG_INFO, "ns_resp: sendto(%s): %m",
  1176.                    sin_ntoa(nsa));
  1177.         nameserIncr(nsa->sin_addr, nssSendtoErr);
  1178.     }
  1179.     hp->rd = 0;    /* leave set to 0 for dup detection */
  1180.     nameserIncr(nsa->sin_addr, nssSentFwdR);
  1181.     nameserIncr(qp->q_from.sin_addr, nssRcvdFwdR);
  1182.     dprintf(3, (ddt, "resp: Query sent.\n"));
  1183. #ifdef    DATUMREFCNT
  1184.     free_nsp(nsp);
  1185. #endif
  1186.     return;
  1187.  
  1188.  formerr:
  1189.     if (!haveComplained((char*)from_addr.sin_addr.s_addr,
  1190.                 (char*)nhash(formerrmsg)))
  1191.         syslog(LOG_INFO, "Malformed response from %s (%s)\n",
  1192.                sin_ntoa(&from_addr), formerrmsg);
  1193.     nameserIncr(from_addr.sin_addr, nssSentFErr);
  1194. #ifdef    DATUMREFCNT
  1195.     free_nsp(nsp);
  1196. #endif
  1197.     return;
  1198.  
  1199.  return_msg:
  1200.     nameserIncr(from_addr.sin_addr, nssRcvdFwdR);
  1201.     nameserIncr(qp->q_from.sin_addr, nssSentFwdR);
  1202.     /* The "standard" return code */
  1203.     hp->qr = 1;
  1204.     hp->id = qp->q_id;
  1205.     hp->rd = 1;
  1206.     hp->ra = (NoRecurse == 0);
  1207.     (void) send_msg(msg, msglen, qp);
  1208.     qremove(qp);
  1209. #ifdef    DATUMREFCNT
  1210.     free_nsp(nsp);
  1211. #endif
  1212.     return;
  1213.  
  1214.  return_newmsg:
  1215.     nameserIncr(qp->q_from.sin_addr, nssSentAns);
  1216.  
  1217. #ifdef XSTATS
  1218.     if (!hp->aa)
  1219.         nameserIncr(qp->q_from.sin_addr, nssSentNaAns);
  1220.     if (hp->rcode == NXDOMAIN) 
  1221.         nameserIncr(qp->q_from.sin_addr, nssSentNXD);
  1222. #endif
  1223.     n = doaddinfo(hp, cp, buflen);
  1224.     cp += n;
  1225.     buflen -= n;
  1226.     hp->qr = 1;
  1227.     hp->id = qp->q_id;
  1228.     hp->rd = 1;
  1229.     hp->ra = (NoRecurse == 0);
  1230.     (void) send_msg(newmsg, cp - newmsg, qp);
  1231.     qremove(qp);
  1232. #ifdef    DATUMREFCNT
  1233.     free_nsp(nsp);
  1234. #endif
  1235.     return;
  1236.  
  1237.  servfail:
  1238.     nameserIncr(qp->q_from.sin_addr, nssSentFail);
  1239.     hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg);
  1240.     hp->rcode = SERVFAIL;
  1241.     hp->qr = 1;
  1242.     hp->id = qp->q_id;
  1243.     hp->rd = 1;
  1244.     hp->ra = (NoRecurse == 0);
  1245.     (void) send_msg((u_char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen),
  1246.             qp);
  1247.     qremove(qp);
  1248. #ifdef    DATUMREFCNT
  1249.     free_nsp(nsp);
  1250. #endif
  1251.     return;
  1252. }
  1253.  
  1254. /*
  1255.  * Decode the resource record 'rrp' and update the database.
  1256.  * If savens is non-nil, record pointer for forwarding queries a second time.
  1257.  */
  1258. int
  1259. doupdate(msg, msglen, rrp, zone, savens, flags, cred)
  1260.     u_char *msg, *rrp;
  1261.     struct databuf **savens;
  1262.     int msglen, zone, flags;
  1263.     u_int cred;
  1264. {
  1265.     register u_char *cp;
  1266.     register int n;
  1267.     int class, type, dlen, n1;
  1268.     u_int32_t ttl;
  1269.     struct databuf *dp;
  1270.     char dname[MAXDNAME];
  1271.     u_char *cp1;
  1272.     u_char data[BUFSIZ];
  1273.     register HEADER *hp = (HEADER *)msg;
  1274. #ifdef ALLOW_UPDATES
  1275.     int zonenum;
  1276. #endif
  1277.  
  1278.     dprintf(3, (ddt, "doupdate(zone %d, savens %#lx, flags %#lx)\n",
  1279.             zone, (u_long)savens, (u_long)flags));
  1280.  
  1281.     cp = rrp;
  1282.     if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname)) < 0) {
  1283.         hp->rcode = FORMERR;
  1284.         return (-1);
  1285.     }
  1286.     cp += n;
  1287.     GETSHORT(type, cp);
  1288.     GETSHORT(class, cp);
  1289.     GETLONG(ttl, cp);
  1290.     GETSHORT(dlen, cp);
  1291.     dprintf(3, (ddt, "doupdate: dname %s type %d class %d ttl %d\n",
  1292.             dname, type, class, ttl));
  1293.     /*
  1294.      * Convert the resource record data into the internal
  1295.      * database format.
  1296.      */
  1297.     switch (type) {
  1298.     case T_A:
  1299.         if (dlen != INT32SZ) {
  1300.             hp->rcode = FORMERR;
  1301.             return (-1);
  1302.         }
  1303.         /*FALLTHROUGH*/
  1304.     case T_WKS:
  1305.     case T_HINFO:
  1306.     case T_UINFO:
  1307.     case T_UID:
  1308.     case T_GID:
  1309.     case T_TXT:
  1310.     case T_X25:
  1311.     case T_ISDN:
  1312.     case T_NSAP:
  1313.     case T_LOC:
  1314. #ifdef ALLOW_T_UNSPEC
  1315.     case T_UNSPEC:
  1316. #endif
  1317.         cp1 = cp;
  1318.         n = dlen;
  1319.         cp += n;
  1320.         break;
  1321.  
  1322.     case T_CNAME:
  1323.     case T_MB:
  1324.     case T_MG:
  1325.     case T_MR:
  1326.     case T_NS:
  1327.     case T_PTR:
  1328.         n = dn_expand(msg, msg + msglen, cp,
  1329.                   (char *)data, sizeof data);
  1330.         if (n < 0) {
  1331.             hp->rcode = FORMERR;
  1332.             return (-1);
  1333.         }
  1334.         cp += n;
  1335.         cp1 = data;
  1336.         n = strlen((char *)data) + 1;
  1337.         break;
  1338.  
  1339.     case T_MINFO:
  1340.     case T_SOA:
  1341.     case T_RP:
  1342.         n = dn_expand(msg, msg + msglen, cp,
  1343.                   (char *)data, sizeof data);
  1344.         if (n < 0) {
  1345.             hp->rcode = FORMERR;
  1346.             return (-1);
  1347.         }
  1348.         cp += n;
  1349.         cp1 = data + (n = strlen((char *)data) + 1);
  1350.         n1 = sizeof(data) - n;
  1351.         if (type == T_SOA)
  1352.             n1 -= 5 * INT32SZ;
  1353.         n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1);
  1354.         if (n < 0) {
  1355.             hp->rcode = FORMERR;
  1356.             return (-1);
  1357.         }
  1358.         cp += n;
  1359.         cp1 += strlen((char *)cp1) + 1;
  1360.         if (type == T_SOA) {
  1361.             bcopy(cp, cp1, n = 5 * INT32SZ);
  1362.             cp += n;
  1363.             cp1 += n;
  1364.         }
  1365.         n = cp1 - data;
  1366.         cp1 = data;
  1367.         break;
  1368.  
  1369.     case T_MX:
  1370.     case T_AFSDB:
  1371.     case T_RT:
  1372.         /* grab preference */
  1373.         bcopy(cp, data, INT16SZ);
  1374.         cp1 = data + INT16SZ;
  1375.         cp += INT16SZ;
  1376.  
  1377.         /* get name */
  1378.         n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
  1379.                   sizeof data - INT16SZ);
  1380.         if (n < 0) {
  1381.             hp->rcode = FORMERR;
  1382.             return (-1);
  1383.         }
  1384.         cp += n;
  1385.  
  1386.         /* compute end of data */
  1387.         cp1 += strlen((char *)cp1) + 1;
  1388.         /* compute size of data */
  1389.         n = cp1 - data;
  1390.         cp1 = data;
  1391.         break;
  1392.  
  1393.     case T_PX:
  1394.         /* grab preference */
  1395.         bcopy(cp, data, INT16SZ);
  1396.         cp1 = data + INT16SZ;
  1397.         cp += INT16SZ;
  1398.  
  1399.         /* get MAP822 name */
  1400.         n = dn_expand(msg, msg + msglen, cp, (char *)cp1,
  1401.                 sizeof data - INT16SZ);
  1402.         if (n < 0) {
  1403.             hp->rcode = FORMERR;
  1404.             return (-1);
  1405.         }
  1406.         cp += n;
  1407.         cp1 += (n = strlen((char *)cp1) + 1);
  1408.         n1 = sizeof(data) - n;
  1409.         n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1);
  1410.         if (n < 0) {
  1411.             hp->rcode = FORMERR;
  1412.             return (-1);
  1413.         }
  1414.         cp += n;
  1415.         cp1 += strlen((char *)cp1) + 1;
  1416.         n = cp1 - data;
  1417.         cp1 = data;
  1418.         break;
  1419.  
  1420.     default:
  1421.         dprintf(3, (ddt, "unknown type %d\n", type));
  1422.         return ((cp - rrp) + dlen);
  1423.     }
  1424.     if (n > MAXDATA) {
  1425.         dprintf(1, (ddt,
  1426.                 "update type %d: %d bytes is too much data\n",
  1427.                 type, n));
  1428.         hp->rcode = FORMERR;
  1429.         return (-1);
  1430.     }
  1431.  
  1432. #ifdef ALLOW_UPDATES
  1433.     /*
  1434.      * If this is a dynamic update request, process it specially; else,
  1435.      * execute normal update code.
  1436.      */
  1437.     switch(hp->opcode) {
  1438.  
  1439.     /* For UPDATEM and UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA */
  1440.     case UPDATEM:
  1441.     case UPDATEMA:
  1442.  
  1443.     /*
  1444.      * The named code for UPDATED and UPDATEDA is the same except that for
  1445.      * UPDATEDA we we ignore any data that was passed: we just delete all
  1446.      * RRs whose name, type, and class matches
  1447.      */
  1448.     case UPDATED:
  1449.     case UPDATEDA:
  1450.         if (type == T_SOA) {    /* Not allowed */
  1451.             dprintf(1, (ddt, "UDPATE: REFUSED - SOA delete\n"));
  1452.             hp->rcode = REFUSED;
  1453.             return (-1);
  1454.         }
  1455.         /*
  1456.          * Don't check message length if doing UPDATEM/UPDATEMA,
  1457.          * since the whole message wont have been demarshalled until
  1458.          * we reach the code for UPDATEA
  1459.          */
  1460.         if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) {
  1461.             if (cp != (u_char *)(msg + msglen)) {
  1462.                 dprintf(1, (ddt, 
  1463.                       "FORMERR UPDATE message length off\n"
  1464.                         ));
  1465.                 hp->rcode = FORMERR;
  1466.                 return (-1);
  1467.             }
  1468.         }
  1469.         if ((zonenum = findzone(dname, class)) == 0) { 
  1470.             hp->rcode = NXDOMAIN;
  1471.             return (-1);
  1472.         }
  1473.         if (zones[zonenum].z_flags & Z_DYNADDONLY) {
  1474.             hp->rcode = NXDOMAIN;
  1475.             return (-1);
  1476.         }
  1477.         if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEM) ) {
  1478.             /* Make a dp for use in db_update, as old dp */
  1479.             dp = savedata(class, type, 0, cp1, n);
  1480.             dp->d_zone = zonenum;
  1481.             dp->d_cred = cred;
  1482.             dp->d_clev = db_getclev(zones[zonenum].z_origin);
  1483.             n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE,
  1484.                       hashtab);
  1485.             if (n != OK) {
  1486.                 dprintf(1, (ddt,
  1487.                         "UPDATE: db_update failed\n"));
  1488.                 free((char*) dp);
  1489.                 hp->rcode = NOCHANGE;
  1490.                 return (-1);
  1491.             }
  1492.         } else {    /* UPDATEDA or UPDATEMA */
  1493.             int DeletedOne = 0;
  1494.             /* Make a dp for use in db_update, as old dp */
  1495.             dp = savedata(class, type, 0, NULL, 0);
  1496.             dp->d_zone = zonenum;
  1497.             dp->d_cred = cred;
  1498.             dp->d_clev = db_getclev(zones[zonenum].z_origin);
  1499.             do {    /* Loop and delete all matching RR(s) */
  1500.                 n = db_update(dname, dp, NULL, DB_DELETE,
  1501.                           hashtab);
  1502.                 if (n != OK)
  1503.                     break;
  1504.                 DeletedOne++;
  1505.             } while (1);
  1506.             free((char*) dp);
  1507.             /* Ok for UPDATEMA not to have deleted any RRs */
  1508.             if (!DeletedOne && hp->opcode == UPDATEDA) {
  1509.                 dprintf(1, (ddt,
  1510.                         "UPDATE: db_update failed\n"));
  1511.                 hp->rcode = NOCHANGE;
  1512.                 return (-1);
  1513.             }
  1514.         }
  1515.         if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) )
  1516.             return (cp - rrp);;
  1517.         /*
  1518.          * Else unmarshal the RR to be added and continue on to
  1519.          * UPDATEA code for UPDATEM/UPDATEMA
  1520.          */
  1521.         if ((n =
  1522.            dn_expand(msg, msg+msglen, cp, dname, sizeof(dname))) < 0) {
  1523.             dprintf(1, (ddt,
  1524.                     "FORMERR UPDATE expand name failed\n"));
  1525.             hp->rcode = FORMERR;
  1526.             return (-1);
  1527.         }
  1528.         cp += n;
  1529.         GETSHORT(type, cp);
  1530.         GETSHORT(class, cp);
  1531.         GETLONG(ttl, cp);
  1532.         GETSHORT(n, cp);
  1533.         cp1 = cp;
  1534. /**** XXX - need bounds checking here ****/
  1535.         cp += n;
  1536.  
  1537.     case UPDATEA:
  1538.         if (n > MAXDATA) {
  1539.             dprintf(1, (ddt, "UPDATE: too much data\n"));
  1540.             hp->rcode = NOCHANGE;
  1541.             return (-1);
  1542.         }
  1543.         if (cp != (u_char *)(msg + msglen)) {
  1544.             dprintf(1, (ddt,
  1545.                     "FORMERR UPDATE message length off\n"));
  1546.             hp->rcode = FORMERR;
  1547.             return (-1);
  1548.         }
  1549.         if ((zonenum = findzone(dname, class)) == 0) { 
  1550.             hp->rcode = NXDOMAIN;
  1551.             return (-1);
  1552.         }
  1553.         if (zones[zonenum].z_flags & Z_DYNADDONLY) {
  1554.             struct hashbuf *htp = hashtab;
  1555.             char *fname;
  1556.             if (nlookup(dname, &htp, &fname, 0) &&
  1557.                 !strcasecmp(dname, fname)) {
  1558.                 dprintf(1, (ddt,
  1559.                         "refusing add of existing name\n"
  1560.                         ));
  1561.                 hp->rcode = REFUSED;
  1562.                 return (-1);
  1563.             }
  1564.         }
  1565.         dp = savedata(class, type, ttl, cp1, n);
  1566.         dp->d_zone = zonenum;
  1567.         dp->d_cred = cred;
  1568.         dp->d_clev = db_getclev(zones[zonenum].z_origin);
  1569.         if ((n = db_update(dname, NULL, dp, DB_NODATA,
  1570.                    hashtab)) != OK) {
  1571.             dprintf(1, (ddt, "UPDATE: db_update failed\n"));
  1572.             hp->rcode = NOCHANGE;
  1573.             free((char*) dp);
  1574.             return (-1);
  1575.         }
  1576.         else
  1577.             return (cp - rrp);
  1578.     }
  1579. #endif /* ALLOW_UPDATES */
  1580.  
  1581.     if (zone == 0)
  1582.         ttl += tt.tv_sec;
  1583. #if defined(TRACEROOT) || defined(BOGUSNS)
  1584.     if ((type == T_NS) && (savens != NULL)) {
  1585.         char *temp, qname[MAXDNAME];
  1586.         register int bogus = 0;
  1587.         int bogusns = 0;
  1588. #ifdef BOGUSNS
  1589.         if (addr_on_netlist(from_addr.sin_addr, boglist)) {
  1590.             bogusns++;
  1591.             bogus++;
  1592.         }
  1593. #endif
  1594.         if (!bogus &&
  1595.             ((temp = strrchr((char *)data, '.')) != NULL) &&
  1596.              !strcasecmp(temp, ".arpa")
  1597.              )
  1598.             bogus++;
  1599.         qname[0] = qname[1] = '\0';
  1600.         if (dn_expand(msg, msg + msglen, msg + HFIXEDSZ,
  1601.                   qname, sizeof(qname)) < 0)
  1602.             qname[0] = '?';
  1603.         else if (qname[0] == '\0')
  1604.             qname[0] = '.';
  1605.         if (bogus && ((dname[0] == '\0') && (zone == 0))) {
  1606.             if (!haveComplained((char*)from_addr.sin_addr.s_addr,
  1607.                         "bogus root NS"))
  1608.                 syslog(LOG_NOTICE,
  1609.              "bogus root NS %s rcvd from %s on query for \"%s\"",
  1610.                        data, sin_ntoa(&from_addr), qname);
  1611.             return (cp - rrp);
  1612.         }
  1613. #ifdef BOGUSNS
  1614.         if (bogusns) {
  1615.             if (!haveComplained((char*)from_addr.sin_addr.s_addr,
  1616.                         "bogus nonroot NS"))
  1617.                 syslog(LOG_INFO,
  1618.             "bogus nonroot NS %s rcvd from %s on query for \"%s\"",
  1619.                        data, sin_ntoa(&from_addr), qname);
  1620.             return (cp - rrp);
  1621.         }
  1622. #endif
  1623.     }
  1624. #endif /*TRACEROOT || BOGUSNS*/
  1625.  
  1626.     dp = savedata(class, type, ttl, cp1, n);
  1627.     dp->d_zone = zone;
  1628.     dp->d_cred = cred;
  1629.     dp->d_clev = 0;    /* We trust what is on disk more, except root srvrs */
  1630.     if ((n = db_update(dname, dp, dp, flags, hashtab)) != OK) {
  1631. #ifdef DEBUG
  1632.         if (debug && (n != DATAEXISTS))
  1633.             fprintf(ddt, "update failed (%d)\n", n);
  1634.         else if (debug >= 3)
  1635.             fprintf(ddt, "update failed (DATAEXISTS)\n");
  1636. #endif
  1637.         free((char *)dp);
  1638.     } else if (type == T_NS && savens != NULL)
  1639.         *savens = dp;
  1640.     return (cp - rrp);
  1641. }
  1642.  
  1643. int
  1644. send_msg(msg, msglen, qp)
  1645.     u_char *msg;
  1646.     int msglen;
  1647.     struct qinfo *qp;
  1648. {
  1649.     if (qp->q_flags & Q_SYSTEM)
  1650.         return (1);
  1651. #ifdef DEBUG
  1652.     if (debug) {
  1653.         fprintf(ddt,"send_msg -> %s (%s %d) id=%d\n",
  1654.             sin_ntoa(&qp->q_from), 
  1655.             qp->q_stream == QSTREAM_NULL ? "UDP" : "TCP",
  1656.             qp->q_stream == QSTREAM_NULL ? qp->q_dfd
  1657.                              : qp->q_stream->s_rfd,
  1658.             ntohs(qp->q_id));
  1659.     }
  1660.     if (debug > 4) {
  1661.         struct qinfo *tqp;
  1662.  
  1663.         for (tqp = nsqhead; tqp!=QINFO_NULL; tqp = tqp->q_link) {
  1664.             fprintf(ddt,
  1665.                 "qp %#lx q_id: %d  q_nsid: %d q_msglen: %d ",
  1666.                 (u_long)tqp, tqp->q_id,
  1667.                 tqp->q_nsid, tqp->q_msglen);
  1668.             fprintf(ddt,
  1669.                 "q_naddr: %d q_curaddr: %d\n",
  1670.                 tqp->q_naddr, tqp->q_curaddr);
  1671.             fprintf(ddt, "q_next: %#lx q_link: %#lx\n",
  1672.                 (u_long)qp->q_next, (u_long)qp->q_link);
  1673.         }
  1674.     }
  1675.     if (debug > 5)
  1676.         fp_nquery(msg, msglen, ddt);
  1677. #endif /* DEBUG */
  1678.     if (qp->q_stream == QSTREAM_NULL) {
  1679.         if (sendto(qp->q_dfd, (char*)msg, msglen, 0,
  1680.                (struct sockaddr *)&qp->q_from,
  1681.                sizeof(qp->q_from)) < 0) {
  1682.             if (!haveComplained((char*)qp->q_from.sin_addr.s_addr,
  1683.                         sendtoStr))
  1684. #if defined(SPURIOUS_ECONNREFUSED)
  1685.                            if (errno != ECONNREFUSED)
  1686. #endif
  1687.                 syslog(LOG_INFO,
  1688.                        "send_msg: sendto(%s): %m",
  1689.                        sin_ntoa(&qp->q_from));
  1690.             nameserIncr(qp->q_from.sin_addr, nssSendtoErr);
  1691.             return (1);
  1692.         }
  1693.     } else {
  1694.         (void) writemsg(qp->q_stream->s_rfd, (u_char*)msg, msglen);
  1695.         sq_done(qp->q_stream);
  1696.     }
  1697.     return (0);
  1698. }
  1699.  
  1700. #ifdef notdef
  1701. /* i don't quite understand this but the only ref to it is notdef'd --vix */
  1702. prime(class, type, oqp)
  1703.     int class, type;
  1704.     register struct qinfo *oqp;
  1705. {
  1706.     char    dname[BUFSIZ];
  1707.  
  1708.     if (oqp->q_msg == NULL)
  1709.         return;
  1710.     if (dn_expand((u_char *)oqp->q_msg,
  1711.         (u_char *)oqp->q_msg + oqp->q_msglen,
  1712.         (u_char *)oqp->q_msg + HFIXEDSZ, (u_char *)dname,
  1713.         sizeof(dname)) < 0)
  1714.         return;
  1715.     dprintf(2, (ddt, "prime: %s\n", dname));
  1716.     (void) sysquery(dname, class, type, NULL, 0, QUERY);
  1717. }
  1718. #endif
  1719.  
  1720. void
  1721. prime_cache()
  1722. {
  1723.     register struct qinfo *qp;
  1724.  
  1725.     dprintf(1, (ddt, "prime_cache: priming = %d\n", priming));
  1726.     if (!priming && fcachetab->h_tab[0] != NULL && !forward_only) {
  1727.         priming++;
  1728.         if (!(qp = sysquery("", C_IN, T_NS, NULL, 0, QUERY)))
  1729.             priming = 0;
  1730.         else
  1731.             qp->q_flags |= (Q_SYSTEM | Q_PRIMING);
  1732.     }
  1733.     needs_prime_cache = 0;
  1734.     return;
  1735. }
  1736.  
  1737. #ifdef BIND_NOTIFY
  1738. struct notify *
  1739. findNotifyPeer(zp, ina)
  1740.     const struct zoneinfo *zp;
  1741.     struct in_addr ina;
  1742. {
  1743.     register struct notify *ap;
  1744.  
  1745.     for (ap = zp->z_notifylist; ap; ap = ap->next)
  1746.         if (ap->addr.s_addr == ina.s_addr)
  1747.             break;
  1748.     return (ap);
  1749. }
  1750.  
  1751. /* sysnotify(dname, class, type)
  1752.  *    cause a NOTIFY request to be sysquery()'d to each secondary server
  1753.  *    of the zone that "dname" is within.
  1754.  */
  1755. void
  1756. sysnotify(dname, class, type)
  1757.     const char *dname;
  1758.     int class, type;
  1759. {
  1760.     char *soaname, *zname;
  1761.     const char *fname;
  1762.     register struct databuf *dp;
  1763.     struct in_addr nss[NSMAX];
  1764.     int nns, na, zn, nsc;
  1765.     struct hashbuf *htp;
  1766.     struct zoneinfo *zp;
  1767.     struct notify *ap;
  1768.     struct namebuf *np;
  1769.  
  1770.     htp = hashtab;
  1771.     np = nlookup(dname, &htp, &fname, 0);
  1772.     if (!np)
  1773.         panic(-1, "sysnotify: can't find name");
  1774.     zn = findMyZone(np, class);
  1775.     if (zn == DB_Z_CACHE)
  1776.         panic(-1, "sysnotify: not auth zone");
  1777.     zp = &zones[zn];
  1778.     if (zp->z_type != Z_PRIMARY && zp->z_type != Z_SECONDARY)
  1779.         panic(-1, "sysnotify: not pri/sec");
  1780.     zname = zp->z_origin;
  1781. /*
  1782. **DBG**    syslog(LOG_INFO, "sysnotify: found \"%s\" in \"%s\" (%s)",
  1783. **DBG**           dname, zname, zoneTypeString(zp));
  1784. */
  1785.     nns = na = 0;
  1786.     /*
  1787.      * Send to recent AXFR peers.
  1788.      */
  1789.     for (ap = zp->z_notifylist; ap; ap = ap->next) {
  1790.         if (tt.tv_sec - ap->last >= zp->z_refresh) {
  1791.             /* XXX - probably should do GC here. */
  1792.             continue;
  1793.         }
  1794.         nss[0] = ap->addr;
  1795.         nsc = 1;
  1796.         nns++;
  1797.         na++;
  1798.         sysquery(dname, class, T_SOA, nss, nsc, NS_NOTIFY_OP);
  1799.     }
  1800.     if (zp->z_type != Z_PRIMARY)
  1801.         goto done;
  1802.     /*
  1803.      * Master.
  1804.      */
  1805.     htp = hashtab;
  1806.     np = nlookup(zname, &htp, &fname, 0);
  1807.     if (!np)
  1808.         panic(-1, "sysnotify: found name but not zone");
  1809.     soaname = NULL;
  1810.     for (dp = np->n_data; dp; dp = dp->d_next) {
  1811.         if (!dp->d_zone || !match(dp, class, T_SOA))
  1812.             continue;
  1813.         if (soaname) {
  1814.             syslog(LOG_NOTICE, "multiple SOA's for zone \"%s\"?",
  1815.                    zname);
  1816.             return;
  1817.         }
  1818.         soaname = (char *) dp->d_data;
  1819.     }
  1820.     if (!soaname) {
  1821.         syslog(LOG_NOTICE, "no SOA found for zone \"%s\"", zname);
  1822.         return;
  1823.     }
  1824.  
  1825.     for (dp = np->n_data; dp; dp = dp->d_next) {
  1826.         register struct databuf *adp;
  1827.         struct namebuf *anp;
  1828.  
  1829.         if (!dp->d_zone || !match(dp, class, T_NS))
  1830.             continue;
  1831.         /* NS RDATA is server name. */
  1832.         if (strcasecmp((char*)dp->d_data, soaname) == 0)
  1833.             continue;
  1834.         htp = hashtab;
  1835.         anp = nlookup((char*)dp->d_data, &htp, &fname, 0);
  1836.         if (!anp) {
  1837.             syslog(LOG_INFO, "sysnotify: can't nlookup(%s)?",
  1838.                    (char*)dp->d_data);
  1839.             continue;
  1840.         }
  1841.         nsc = 0;
  1842.         for (adp = anp->n_data; adp; adp = adp->d_next) {
  1843.             struct in_addr ina;
  1844.             if (!match(adp, class, T_A))
  1845.                 continue;
  1846.             ina = data_inaddr(adp->d_data);
  1847.             /* Don't send to things we handled above. */
  1848.             ap = findNotifyPeer(zp, ina);
  1849.             if (ap && tt.tv_sec - ap->last < zp->z_refresh)
  1850.                 goto nextns;
  1851.             if (nsc < NSMAX)
  1852.                 nss[nsc++] = ina;
  1853.         } /*next A*/
  1854.         if (nsc == 0) {
  1855.             struct qinfo *qp;
  1856.  
  1857.             qp = sysquery((char*)dp->d_data,    /*NS name*/
  1858.                       class,            /*XXX: C_IN?*/
  1859.                       T_A, 0, 0, QUERY);
  1860.             if (qp)
  1861.                 qp->q_notifyzone = zn;
  1862.             continue;
  1863.         }
  1864.         (void) sysquery(dname, class, T_SOA, nss, nsc, NS_NOTIFY_OP);
  1865.         nns++;
  1866.         na += nsc;
  1867.  nextns:;
  1868.     } /*next NS*/
  1869.  done:
  1870.     if (nns || na) {
  1871.         char tmp[MAXDNAME*2];
  1872.  
  1873.         /* Many syslog()'s only take 5 args. */
  1874.         sprintf(tmp, "%s %s %s", dname, p_class(class), p_type(type));
  1875.         syslog(LOG_INFO, "Sent NOTIFY for \"%s\" (%s); %d NS, %d A",
  1876.                tmp, zname, nns, na);
  1877.     }
  1878. }
  1879. #endif /*BIND_NOTIFY*/
  1880.  
  1881. struct qinfo *
  1882. sysquery(dname, class, type, nss, nsc, opcode)
  1883.     const char *dname;
  1884.     int class, type;
  1885.     struct in_addr *nss;
  1886.     int nsc, opcode;
  1887. {
  1888.     register struct qinfo *qp, *oqp;
  1889.     register HEADER *hp;
  1890.     struct namebuf *np;
  1891.     struct databuf *nsp[NSMAX];
  1892.     struct hashbuf *htp;
  1893.     struct sockaddr_in *nsa;
  1894.     const char *fname;
  1895.     int n, count;
  1896.  
  1897. #ifdef    DATUMREFCNT
  1898.     nsp[0] = NULL;
  1899. #endif
  1900.     dprintf(3, (ddt, "sysquery(%s, %d, %d, %#lx, %d)\n",
  1901.             dname, class, type, (u_long)nss, nsc));
  1902.     qp = qnew();
  1903.  
  1904.     if (nss && nsc) {
  1905.         np = NULL;
  1906.     } else {
  1907.         htp = hashtab;
  1908.         if (priming && dname[0] == '\0') {
  1909.             np = NULL;
  1910.         } else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) {
  1911.             syslog(LOG_INFO, "sysquery: nlookup error on %s?",
  1912.                    dname);
  1913.  err1:
  1914.             qfree(qp);
  1915.             return (NULL);
  1916.         }
  1917.  
  1918.         n = findns(&np, class, nsp, &count, 0);
  1919.         switch (n) {
  1920.         case NXDOMAIN:
  1921.         case SERVFAIL:
  1922.             syslog(LOG_DEBUG, "sysquery: findns error (%d) on %s?",
  1923.                    n, dname);
  1924.  err2:
  1925. #ifdef    DATUMREFCNT
  1926.             free_nsp(nsp);
  1927. #endif
  1928.             goto err1;
  1929.         }
  1930.     }
  1931.  
  1932.     /* build new qinfo struct */
  1933.     qp->q_cmsg = qp->q_msg = NULL;
  1934.     qp->q_dfd = ds;
  1935.     if (nss && nsc)
  1936.         qp->q_fwd = NULL;
  1937.     else
  1938.         qp->q_fwd = fwdtab;
  1939.     qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;
  1940.     qp->q_flags |= Q_SYSTEM;
  1941. #if defined(LAME_DELEGATION) || defined(VALIDATE)
  1942.     getname(np, qp->q_domain, sizeof(qp->q_domain));
  1943. #endif /* LAME_DELEGATION */
  1944.  
  1945.     if ((qp->q_msg = (u_char *)malloc(BUFSIZ)) == NULL) {
  1946.         syslog(LOG_NOTICE, "sysquery: malloc failed");
  1947.         goto err2;
  1948.     }
  1949.     n = res_mkquery(opcode, dname, class,
  1950.             type, NULL, 0, NULL,
  1951.             qp->q_msg, BUFSIZ);
  1952.     if (n < 0) {
  1953.         syslog(LOG_INFO, "sysquery: res_mkquery(%s) failed", dname);
  1954.         goto err2;
  1955.     }
  1956.     qp->q_msglen = n;
  1957.     hp = (HEADER *) qp->q_msg;
  1958.     hp->id = qp->q_nsid = htons(nsid_next());
  1959.     hp->rd = (qp->q_fwd ? 1 : 0);
  1960.  
  1961.     /* First check for an already pending query for this data */
  1962.     for (oqp = nsqhead; oqp != QINFO_NULL; oqp = oqp->q_link) {
  1963.         if ((oqp != qp)
  1964.             && (oqp->q_msglen == qp->q_msglen)
  1965.             && bcmp((char *)oqp->q_msg+2,
  1966.                 qp->q_msg+2,
  1967.                 qp->q_msglen-2) == 0
  1968.             ) {
  1969. #ifdef BIND_NOTIFY
  1970.             /* XXX - need fancier test to suppress duplicate
  1971.              *       NOTIFYs to the same server (compare nss?)
  1972.              */
  1973.             if (opcode != NS_NOTIFY_OP)
  1974. #endif /*BIND_NOTIFY*/
  1975.             {
  1976.                 dprintf(3, (ddt, "sysquery: duplicate\n"));
  1977.                 goto err2;
  1978.             }
  1979.         }
  1980.     }
  1981.  
  1982.     if (nss && nsc) {
  1983.         int i;
  1984.         struct qserv *qs;
  1985.  
  1986.         for (i = 0, qs = qp->q_addr;
  1987.              i < nsc;
  1988.              i++, qs++) {
  1989.             qs->ns_addr.sin_family = AF_INET;
  1990.             qs->ns_addr.sin_addr = nss[i];
  1991.             qs->ns_addr.sin_port = ns_port;
  1992.             qs->ns = NULL;
  1993.             qs->nsdata = NULL;
  1994.             qs->stime = tt;
  1995.             qs->nretry = 0;
  1996.         }
  1997.         qp->q_naddr = nsc;
  1998.     } else {
  1999.         count = nslookup(nsp, qp, dname, "sysquery");
  2000.         if (count <= 0) {
  2001.             if (count < 0)
  2002.                 syslog(LOG_INFO,
  2003.                       "sysquery: nslookup reports danger (%s)",
  2004.                        dname);
  2005.             else
  2006.                 /* "." domain gets LOG_WARNING here. */
  2007.                 syslog(dname[0] ? LOG_INFO : LOG_WARNING,
  2008.                        "sysquery: no addrs found for NS (%s)",
  2009.                        dname);
  2010.             goto err2;
  2011.         }
  2012.     }
  2013.  
  2014.     schedretry(qp, retrytime(qp));
  2015.     if (qp->q_fwd == NULL)
  2016.         qp->q_addr[0].stime = tt;    /* XXX - why not every? */
  2017.     nsa = Q_NEXTADDR(qp, 0);
  2018.  
  2019.     dprintf(1, (ddt,
  2020.             "sysquery: send -> %s dfd=%d nsid=%d id=%d retry=%ld\n",
  2021.             sin_ntoa(nsa), qp->q_dfd, 
  2022.             ntohs(qp->q_nsid), ntohs(qp->q_id),
  2023.             qp->q_time));
  2024. #ifdef DEBUG
  2025.     if (debug >= 10)
  2026.         fp_nquery(qp->q_msg, qp->q_msglen, ddt);
  2027. #endif
  2028.     if (sendto(qp->q_dfd, (char*)qp->q_msg, qp->q_msglen, 0,
  2029.            (struct sockaddr *)nsa,
  2030.            sizeof(struct sockaddr_in)) < 0) {
  2031.         if (!haveComplained((char*)nsa->sin_addr.s_addr, sendtoStr))
  2032.             syslog(LOG_INFO, "sysquery: sendto(%s): %m",
  2033.                    sin_ntoa(nsa));
  2034.         nameserIncr(nsa->sin_addr, nssSendtoErr);
  2035.     }
  2036.     nameserIncr(nsa->sin_addr, nssSentSysQ);
  2037. #ifdef    DATUMREFCNT
  2038.     free_nsp(nsp);
  2039. #endif
  2040.     return (qp);
  2041. }
  2042.  
  2043. /*
  2044.  * Check the list of root servers after receiving a response
  2045.  * to a query for the root servers.
  2046.  */
  2047. static void
  2048. check_root()
  2049. {
  2050.     register struct databuf *dp, *pdp;
  2051.     register struct namebuf *np;
  2052.     int count = 0;
  2053.  
  2054.     priming = 0;
  2055.     for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next)
  2056.         if (np->n_dname[0] == '\0')
  2057.             break;
  2058.     if (np == NULL) {
  2059.         syslog(LOG_NOTICE, "check_root: Can't find root!\n");
  2060.         return;
  2061.     }
  2062.     for (dp = np->n_data; dp != NULL; dp = dp->d_next)
  2063.         if (dp->d_type == T_NS)
  2064.             count++;
  2065.     dprintf(1, (ddt, "%d root servers\n", count));
  2066.     if (count < MINROOTS) {
  2067.         syslog(LOG_NOTICE,
  2068.         "check_root: %d root servers after query to root server < min",
  2069.                count);
  2070.         return;
  2071.     }
  2072.     pdp = NULL;
  2073.     dp = np->n_data;
  2074.     while (dp != NULL) {
  2075.         if (dp->d_type == T_NS && dp->d_zone == 0 &&
  2076.             dp->d_ttl < tt.tv_sec) {
  2077.             dprintf(1, (ddt, "deleting old root server '%s'\n",
  2078.                     dp->d_data));
  2079.             dp = rm_datum(dp, np, pdp);
  2080.             /* SHOULD DELETE FROM HINTS ALSO */
  2081.             continue;
  2082.         }
  2083.         pdp = dp;
  2084.         dp = dp->d_next;
  2085.     }
  2086.     check_ns();
  2087. }
  2088.  
  2089. /* 
  2090.  * Check the root to make sure that for each NS record we have a A RR
  2091.  */
  2092. static void
  2093. check_ns()
  2094. {
  2095.     register struct databuf *dp, *tdp;
  2096.     register struct namebuf *np, *tnp;
  2097.     struct hashbuf *htp;
  2098.     char *dname;
  2099.     int found_arr;
  2100.     const char *fname;
  2101.     time_t curtime;
  2102.  
  2103.     dprintf(2, (ddt, "check_ns()\n"));
  2104.  
  2105.     curtime = (u_int32_t) tt.tv_sec;
  2106.     for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) {
  2107.         if (np->n_dname[0] != 0)
  2108.             continue;
  2109.         for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  2110.             if (dp->d_type != T_NS)
  2111.                 continue;
  2112.  
  2113.                 /* look for A records */
  2114.             dname = (caddr_t) dp->d_data;
  2115.             htp = hashtab;
  2116.             tnp = nlookup(dname, &htp, &fname, 0);
  2117.             if (tnp == NULL || fname != dname) {
  2118.                 dprintf(3, (ddt,
  2119.                         "check_ns: %s: not found %s %#lx\n",
  2120.                         dname, fname, (u_long)tnp));
  2121.                 sysquery(dname, dp->d_class, T_A, NULL,
  2122.                      0, QUERY);
  2123.                 continue;
  2124.             }
  2125.             /* look for name server addresses */
  2126.             found_arr = 0;
  2127.             for (tdp=tnp->n_data; tdp != NULL; tdp=tdp->d_next) {
  2128.                 if (tdp->d_type != T_A ||
  2129.                     tdp->d_class != dp->d_class)
  2130.                     continue;
  2131.                 if ((tdp->d_zone == 0) &&
  2132.                     (tdp->d_ttl < curtime)) {
  2133.                     dprintf(3, (ddt,
  2134.                         "check_ns: stale entry '%s'\n",
  2135.                             tnp->n_dname));
  2136.                     /* Cache invalidate the address RR's */
  2137.                     delete_all(tnp, dp->d_class, T_A);
  2138.                     found_arr = 0;
  2139.                     break;
  2140.                 }
  2141.                 found_arr++;
  2142.             }
  2143.             if (!found_arr)
  2144.                 sysquery(dname, dp->d_class, T_A, NULL,
  2145.                      0, QUERY);
  2146.             }
  2147.     }
  2148. }
  2149.  
  2150. /* int findns(npp, class, nsp, countp, flag)
  2151.  *    Find NS' or an SOA
  2152.  * npp, class:
  2153.  *    dname whose most enclosing NS is wanted
  2154.  * nsp, countp:
  2155.  *    result array and count; array will also be NULL terminated
  2156.  * flag:
  2157.  *    boolean: we're being called from ADDAUTH, bypass authority checks
  2158.  * return value:
  2159.  *    NXDOMAIN: we are authoritative for this {dname,class}
  2160.  *    SERVFAIL: we are auth but zone isn't loaded; or, no root servers found
  2161.  *    OK: success (this is the only case where *countp and nsp[] are valid)
  2162.  */
  2163. int
  2164. findns(npp, class, nsp, countp, flag)
  2165.     register struct namebuf **npp;
  2166.     int class;
  2167.     struct databuf **nsp;
  2168.     int *countp;
  2169.     int flag;
  2170. {
  2171.     register struct namebuf *np = *npp;
  2172.     register struct databuf *dp;
  2173.     register struct    databuf **nspp;
  2174.     struct hashbuf *htp;
  2175.     
  2176. #ifdef DATUMREFCNT
  2177.     nsp[0] = NULL;
  2178. #endif
  2179.  
  2180.     if (priming && (np == NULL || np->n_dname[0] == '\0'))
  2181.         htp = fcachetab;
  2182.     else
  2183.         htp = hashtab;
  2184.  
  2185.  try_again:
  2186.     if (htp == fcachetab)
  2187.         needs_prime_cache = 1;
  2188.     while (np == NULL && htp != NULL) {
  2189.         dprintf(3, (ddt, "findns: using %s\n",
  2190.                 htp == hashtab ? "cache" : "hints"));
  2191.         for (np = htp->h_tab[0]; np != NULL; np = np->n_next)
  2192.             if (np->n_dname[0] == '\0')
  2193.                 break;
  2194.         htp = (htp == hashtab ? fcachetab : NULL);    /* Fallback */
  2195.     }
  2196.     while (np != NULL) {
  2197.         dprintf(5, (ddt, "findns: np %#lx '%s'\n",
  2198.                 (u_long)np, np->n_dname));
  2199.         /* Look first for SOA records. */
  2200. #ifdef ADDAUTH
  2201.         if (!flag)
  2202. #endif
  2203.         for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  2204.             if (dp->d_zone != 0 &&
  2205. #ifdef PURGE_ZONE
  2206.                 ((zones[dp->d_zone].z_type == Z_PRIMARY) ||
  2207.                 (zones[dp->d_zone].z_type == Z_SECONDARY)) &&
  2208. #endif
  2209.                 match(dp, class, T_SOA)) {
  2210.                 dprintf(3, (ddt, "findns: SOA found\n"));
  2211.                 if (zones[dp->d_zone].z_flags & Z_AUTH) {
  2212.                     *npp = np;
  2213.                     nsp[0] = dp;
  2214. #ifdef DATUMREFCNT
  2215.                     nsp[1] = NULL;
  2216.                     dp->d_rcnt++;
  2217. #endif
  2218.                     return (NXDOMAIN);
  2219.                 } else {
  2220.                     /* XXX:    zone isn't loaded but we're
  2221.                      *    primary or secondary for it.
  2222.                      *    should we fwd this?
  2223.                      */
  2224.                     return (SERVFAIL);
  2225.                 }
  2226.             }
  2227.         }
  2228.  
  2229.         /* If no SOA records, look for NS records. */
  2230.         nspp = &nsp[0];
  2231.         *nspp = NULL;
  2232.         for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  2233.             if (!match(dp, class, T_NS))
  2234.                 continue;
  2235. #ifdef NCACHE
  2236.             if (dp->d_rcode)
  2237.                 continue;
  2238. #endif
  2239.             /*
  2240.              * Don't use records that may become invalid to
  2241.              * reference later when we do the rtt computation.
  2242.              * Never delete our safety-belt information!
  2243.              *
  2244.              * XXX:    this is horribly bogus.
  2245.              */
  2246.             if ((dp->d_zone == 0) &&
  2247. #ifdef DATUMREFCNT
  2248.                 (dp->d_ttl < tt.tv_sec) &&
  2249. #else
  2250.                 (dp->d_ttl < (tt.tv_sec+900)) &&
  2251. #endif
  2252.                 !(dp->d_flags & DB_F_HINT)) {
  2253.                 dprintf(1, (ddt, "findns: stale entry '%s'\n",
  2254.                         np->n_dname));
  2255.                 /* Cache invalidate the NS RR's. */
  2256. #ifndef DATUMREFCNT
  2257.                 if (dp->d_ttl < tt.tv_sec)
  2258. #endif
  2259.                     delete_all(np, class, T_NS);
  2260.                 goto try_parent;
  2261.             }
  2262.             if (nspp < &nsp[NSMAX-1]) {
  2263.                 *nspp++ = dp;
  2264. #ifdef DATUMREFCNT
  2265.                 dp->d_rcnt++;
  2266. #endif
  2267.             }
  2268.         }
  2269.  
  2270.         *countp = nspp - nsp;
  2271.         if (*countp > 0) {
  2272.             dprintf(3, (ddt, "findns: %d NS's added for '%s'\n",
  2273.                     *countp, np->n_dname));
  2274.             *nspp = NULL;
  2275.             *npp = np;
  2276.             return (OK);    /* Success, got some NS's */
  2277.         }
  2278. try_parent:
  2279.         np = np->n_parent;
  2280.     }
  2281.     if (htp)
  2282.         goto try_again;
  2283.     dprintf(1, (ddt, "findns: No root nameservers for class %s?\n",
  2284.             p_class(class)));
  2285.     if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) {
  2286.         norootlogged[class] = 1;
  2287.         syslog(LOG_INFO, "No root nameservers for class %s\n",
  2288.                p_class(class));
  2289.     }
  2290.     return (SERVFAIL);
  2291. }
  2292.  
  2293. /*
  2294.  * Extract RR's from the given node that match class and type.
  2295.  * Return number of bytes added to response.
  2296.  * If no matching data is found, then 0 is returned.
  2297.  */
  2298. int
  2299. finddata(np, class, type, hp, dnamep, lenp, countp)
  2300.     struct namebuf *np;
  2301.     int class, type;
  2302.     register HEADER *hp;
  2303.     char **dnamep;
  2304.     int *lenp, *countp;
  2305. {
  2306.     register struct databuf *dp;
  2307.     register char *cp;
  2308.     int buflen, n, count = 0, foundstale = 0;
  2309.  
  2310. #ifdef ROUND_ROBIN
  2311.     if (type != T_ANY && type != T_PTR) {
  2312.         /* cycle order of RRs, for a load balancing effect... */
  2313.  
  2314.         register struct databuf **dpp;
  2315.  
  2316.         for (dpp = &np->n_data; dp = *dpp; dpp = &dp->d_next) {
  2317.             if (dp->d_next && wanted(dp, class, type)) {
  2318.                 register struct databuf *lp;
  2319.  
  2320.                 *dpp = lp = dp->d_next;
  2321.                 dp->d_next = NULL;
  2322.  
  2323.                 for (dpp = &lp->d_next;
  2324.                      *dpp;
  2325.                      dpp = &lp->d_next)
  2326.                     lp = *dpp;
  2327.                 *dpp = dp;
  2328.                 break;
  2329.             }
  2330.         }
  2331.     }
  2332. #endif /*ROUND_ROBIN*/
  2333.  
  2334.     buflen = *lenp;
  2335. #ifdef DEBUG
  2336.     if (buflen > PACKETSZ)
  2337.         dprintf(1, (ddt, "finddata(): buflen=%d\n", buflen));
  2338. #endif
  2339.     cp = ((char *)hp) + *countp;
  2340.     for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  2341.         if (!wanted(dp, class, type)) {
  2342. #ifndef NCACHE /*if no negative caching then cname => nothing else*/
  2343.             if (type == T_CNAME && class == dp->d_class) {
  2344.                 /* any data means no CNAME exists */
  2345.                 *countp = 0;
  2346.                 return 0;
  2347.             }
  2348. #endif /*NCACHE*/
  2349.             continue;
  2350.         }
  2351.         if (stale(dp)) {
  2352.             /*
  2353.              * Don't use stale data.
  2354.              * Would like to call delete_all here
  2355.              * and continue, but the data chain would get
  2356.              * munged; can't restart, as make_rr has side
  2357.              * effects (leaving pointers in dnptr).
  2358.              * Just skip this entry for now
  2359.              * and call delete_all at the end.
  2360.              */
  2361.             dprintf(3, (ddt,
  2362.                     "finddata: stale entry '%s'\n",
  2363.                     np->n_dname));
  2364.             if (dp->d_zone == 0)
  2365.                 foundstale++;
  2366.             continue;
  2367.         }
  2368.         if (dp->d_cred == DB_C_ADDITIONAL) {
  2369.             /* we want to expire additional data very
  2370.              * quickly.  current strategy is to cut 5%
  2371.              * off each time it is accessed.  this makes
  2372.              * stale(dp) true faster when this datum is
  2373.              * used often.
  2374.              */
  2375.             dp->d_ttl = tt.tv_sec
  2376.                     +
  2377.                 0.95 * (int) (dp->d_ttl - tt.tv_sec);
  2378.         }
  2379. #ifdef NCACHE
  2380.         /* -ve $ing stuff, anant@isi.edu
  2381.          * if we have a -ve $ed record, change the rcode on the
  2382.          * header to reflect that
  2383.          */
  2384.         if (dp->d_rcode == NOERROR_NODATA) {
  2385.             if (count != 0) {
  2386.                 /*
  2387.                  * This should not happen, yet it does...
  2388.                  */
  2389.                 syslog(LOG_INFO,
  2390.                    "NODATA & data for \"%s\" type %d class %d",
  2391.                        *dnamep, type, class);
  2392.                 continue;
  2393.             }
  2394.             if (type != T_ANY) {
  2395.                 hp->rcode = NOERROR_NODATA;
  2396.                 *countp = 0;
  2397.                 return 1; /* XXX - we have to report success */
  2398.             }
  2399.             /* don't satisfy T_ANY queries from -$ info */
  2400.             continue;
  2401.         }
  2402. #ifndef RETURNSOA
  2403.         if (dp->d_rcode == NXDOMAIN) {
  2404.             if (count != 0) {
  2405.                 /*
  2406.                  * This should not happen, yet it might...
  2407.                  */
  2408.                 syslog(LOG_INFO,
  2409.                   "NXDOMAIN & data for \"%s\" type %d class %d",
  2410.                        *dnamep, type, class);
  2411.                 continue;
  2412.             }
  2413.             if (type != T_ANY) {
  2414.                 hp->rcode = NXDOMAIN;
  2415.                 *countp = 0;
  2416.                 return 1; /* XXX - we have to report success */
  2417.             }
  2418.             /* don't satisfy T_ANY queries from -$ info */
  2419.             continue;
  2420.         }
  2421. #endif
  2422. #endif /*NCACHE*/
  2423.  
  2424.         if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1)) < 0) {
  2425.             hp->tc = 1;
  2426.             *countp = count;
  2427.             return (*lenp - buflen);
  2428.         }
  2429.  
  2430.         cp += n;
  2431.         buflen -= n;
  2432.         count++;
  2433. #ifdef notdef
  2434.         /* this isn't right for glue records, aa is set in ns_req */
  2435.         if (dp->d_zone &&
  2436.             (zones[dp->d_zone].z_flags & Z_AUTH) &&
  2437.             class != C_ANY)
  2438.             hp->aa = 1;            /* XXX */
  2439. #endif
  2440.         if (dp->d_type == T_CNAME) {
  2441.             if (type != T_ANY) {    /* or T_NS? */
  2442.                 *dnamep = (caddr_t) dp->d_data;
  2443.                 if (dp->d_zone != DB_Z_CACHE &&
  2444.                     (zones[dp->d_zone].z_flags & Z_AUTH) &&
  2445.                     class != C_ANY)        /* XXX */
  2446.                     hp->aa = 1;        /* XXX */
  2447.             }
  2448.             break;
  2449.         }
  2450.     }
  2451.     /*
  2452.      * Cache invalidate the other RR's of same type
  2453.      * if some have timed out
  2454.      */
  2455.     if (foundstale) {
  2456.         delete_all(np, class, type);
  2457.         /* XXX this isn't right if 'type' is something special
  2458.          * such as T_AXFR or T_MAILB, since the matching done
  2459.          * by match() in delete_all() is different from that
  2460.          * done by wanted() above.
  2461.          */
  2462.     }
  2463.     dprintf(3, (ddt, "finddata: added %d class %d type %d RRs\n",
  2464.             count, class, type));
  2465.     *countp = count;
  2466.     return (*lenp - buflen);
  2467. }
  2468.  
  2469. /*
  2470.  * Do we want this data record based on the class and type?
  2471.  */
  2472. int
  2473. wanted(dp, class, type)
  2474.     struct databuf *dp;
  2475.     int class, type;
  2476. {
  2477.     dprintf(3, (ddt, "wanted(%#lx, %d, %d) [%s %s]\n",
  2478.             (u_long)dp, class, type,
  2479.             p_class(dp->d_class), p_type(dp->d_type)));
  2480.  
  2481.     if (dp->d_class != class && class != C_ANY)
  2482.         return (0);
  2483.     if (type == dp->d_type)
  2484.         return (1);
  2485. #ifdef NCACHE
  2486.     /*-ve $ing stuff, for a T_ANY query, we do not want to return
  2487.      * -ve $ed RRs.
  2488.      */
  2489.     if (type == T_ANY && dp->d_rcode == NOERROR_NODATA)
  2490.         return (0);
  2491. #endif
  2492.  
  2493.     switch (dp->d_type) {
  2494.     case T_ANY:
  2495.         return (1);
  2496.     case T_CNAME:
  2497. #ifdef NCACHE
  2498.         if (dp->d_rcode != NOERROR_NODATA)
  2499. #endif
  2500.             return (1);
  2501. #ifdef NCACHE
  2502.         else
  2503.             break;
  2504. #endif
  2505.     }
  2506.     switch (type) {
  2507.     case T_ANY:
  2508.         return (1);
  2509.  
  2510.     case T_MAILB:
  2511.         switch (dp->d_type) {
  2512.         case T_MR:
  2513.         case T_MB:
  2514.         case T_MG:
  2515.         case T_MINFO:
  2516.             return (1);
  2517.         }
  2518.         break;
  2519.  
  2520.     case T_AXFR:
  2521.         /* T_AXFR needs an authoritative SOA */
  2522.         if (dp->d_type == T_SOA && dp->d_zone != 0
  2523.             && (zones[dp->d_zone].z_flags & Z_AUTH))
  2524.             return (1);
  2525.         break;
  2526.     }
  2527.     return (0);
  2528. }
  2529.  
  2530. /*
  2531.  *  Add RR entries from dpp array to a query/response.
  2532.  *  Return the number of bytes added or negative the amount
  2533.  *  added if truncation occured.  Typically you are
  2534.  *  adding NS records to a response.
  2535.  */
  2536. int
  2537. add_data(np, dpp, cp, buflen, countp)
  2538.     struct namebuf *np;
  2539.     struct databuf **dpp;
  2540.     register u_char *cp;
  2541.     int buflen, *countp;
  2542. {
  2543.     register struct databuf *dp;
  2544.     char dname[MAXDNAME];
  2545.     register int n, bytes;
  2546.  
  2547.     bytes = *countp = 0;
  2548.     getname(np, dname, sizeof(dname));
  2549.     for (dp = *dpp++; dp != NULL; dp = *dpp++) {
  2550.         if (stale(dp))
  2551.             continue;    /* ignore old cache entry */
  2552. #ifdef NCACHE
  2553.         if (dp->d_rcode)
  2554.             continue;
  2555. #endif
  2556.         if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0)
  2557.             return (-bytes);    /* Truncation */
  2558.         cp += n;
  2559.         buflen -= n;
  2560.         bytes += n;
  2561.         (*countp)++;
  2562.     }
  2563.     return (bytes);
  2564. }
  2565.  
  2566. /*
  2567.  *  This is best thought of as a "cache invalidate" function.
  2568.  *  It is called whenever a piece of data is determined to have
  2569.  *  become invalid either through a timeout or a validation
  2570.  *  failure.  It is better to have no information, than to
  2571.  *  have partial information you pass off as complete.
  2572.  */
  2573. void
  2574. delete_all(np, class, type)
  2575.     register struct namebuf *np;
  2576.     int class, type;
  2577. {
  2578.     register struct databuf *dp, *pdp;
  2579.  
  2580.     dprintf(3, (ddt, "delete_all(%#lx:\"%s\" %s %s)\n",
  2581.             (u_long)np, np->n_dname, p_class(class), p_type(type)));
  2582.     pdp = NULL;
  2583.     dp = np->n_data;
  2584.     while (dp != NULL) {
  2585.         if ((dp->d_zone == 0) && !(dp->d_flags & DB_F_HINT)
  2586.             && match(dp, class, type)) {
  2587.             dp = rm_datum(dp, np, pdp);
  2588.             continue;
  2589.         }
  2590.         pdp = dp;
  2591.         dp = dp->d_next;
  2592.     }
  2593. }
  2594.